mirror of
https://github.com/Z3Prover/z3
synced 2025-04-20 07:36:38 +00:00
Merge branch 'master' into polysat
This commit is contained in:
commit
59c3234fb8
2
.github/workflows/docker-image.yml
vendored
2
.github/workflows/docker-image.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
|||
type=edge
|
||||
type=sha,prefix=ubuntu-20.04-bare-z3-sha-
|
||||
- name: Build and push Bare Z3 Docker Image
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
uses: docker/build-push-action@v4.1.1
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
|
|
@ -81,7 +81,7 @@ if (EXISTS "${GIT_DIR}")
|
|||
# This mimics the behaviour of the old build system.
|
||||
set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3_GIT_DESCRIPTION}")
|
||||
else()
|
||||
message(STATUS "Not including git descrption in version")
|
||||
message(STATUS "Not including git description in version")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Failed to add git dependency.")
|
||||
|
@ -462,7 +462,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
|
|||
# generate files used for Z3's build. Changes to these files will trigger
|
||||
# a rebuild of all the generated files.
|
||||
################################################################################
|
||||
# Note: ``update_api.py`` is deliberately not here because it not used
|
||||
# Note: ``update_api.py`` is deliberately not here because it is not used
|
||||
# to generate every generated file. The targets that need it list it explicitly.
|
||||
set(Z3_GENERATED_FILE_EXTRA_DEPENDENCIES
|
||||
"${PROJECT_SOURCE_DIR}/scripts/mk_genfile_common.py"
|
||||
|
|
|
@ -125,7 +125,7 @@ Note that this is `libz3` not `z3` (`libz3` refers to the library target from `s
|
|||
|
||||
[Ninja](https://ninja-build.org/) is a simple build system that is built for speed.
|
||||
It can be significantly faster than "UNIX Makefile"s because it is not a recursive
|
||||
build system and thus doesn't create a new process everytime it traverses into a directory.
|
||||
build system and thus doesn't create a new process every time it traverses into a directory.
|
||||
Ninja is particularly appropriate if you want fast incremental building.
|
||||
|
||||
Basic usage is as follows:
|
||||
|
@ -236,7 +236,7 @@ more interactive and allow you to change various options. In both these
|
|||
tools the basic steps to follow are:
|
||||
|
||||
1. Configure.
|
||||
2. Change any options you wish. Everytime you change a set of options
|
||||
2. Change any options you wish. Every time you change a set of options
|
||||
You should configure again. This may cause new options to appear
|
||||
3. Generate.
|
||||
|
||||
|
@ -348,7 +348,7 @@ These notes are help developers and packagers of Z3.
|
|||
### Install/Uninstall
|
||||
|
||||
Install and uninstall targets are supported. Use ``CMAKE_INSTALL_PREFIX`` to
|
||||
set the install prefix. If you also need need to control which directories are
|
||||
set the install prefix. If you also need to control which directories are
|
||||
used for install set the documented ``CMAKE_INSTALL_*`` options.
|
||||
|
||||
To install run
|
||||
|
|
|
@ -62,7 +62,7 @@ Version 4.12.0
|
|||
Clauses that are deduced by theories are marked by default
|
||||
by 'smt', and when more detailed information
|
||||
is available with proof hints or proof objects.
|
||||
Instantations are considered useful to track so they
|
||||
Instantiations are considered useful to track so they
|
||||
are logged using terms of the form
|
||||
|
||||
(inst (not (forall (x) body)) body[t/x] (bind t)), where
|
||||
|
@ -88,7 +88,7 @@ Version 4.12.0
|
|||
checker cannot check. It is mainly a limitation
|
||||
of the arithmetic solver not pulling relevant information.
|
||||
Ensuring a tight coupling with proof hints and the validator
|
||||
capabilites is open ended future work and good material for theses.
|
||||
capabilities is open ended future work and good material for theses.
|
||||
- bit-vector inferences - are treated as trusted
|
||||
(there is no validation, it always blindly succeeds)
|
||||
- arrays, datatypes - there is no custom validation for
|
||||
|
@ -158,13 +158,13 @@ Version 4.11.2
|
|||
with SMT format that is extensible. The resulting format is a mild extension of SMTLIB with
|
||||
three extra commands assume, learn, del. They track input clauses, generated clauses and deleted clauses.
|
||||
They are optionally augmented by proof hints. Two proof hints are used in the current version: "rup" and "farkas".
|
||||
"rup" is used whent the generated clause can be justified by reverse unit propagation. "farkas" is used when
|
||||
"rup" is used when the generated clause can be justified by reverse unit propagation. "farkas" is used when
|
||||
the clause can be justified by a combination of Farkas cutting planes. There is a built-in proof checker for the
|
||||
format. Quantifier instantiations are also tracked as proof hints.
|
||||
Other proof hints are to be added as the feature set is tested and developed. The fallback, buit-in,
|
||||
Other proof hints are to be added as the feature set is tested and developed. The fallback, built-in,
|
||||
self-checker uses z3 to check that the generated clause is a consequence. Note that this is generally
|
||||
insufficient as generated clauses are in principle required to only be satisfiability preserving.
|
||||
Proof checking and tranformation operations is overall open ended.
|
||||
Proof checking and transformation operations is overall open ended.
|
||||
The log for the first commit introducing this change contains further information on the format.
|
||||
- fix to re-entrancy bug in user propagator (thanks to Clemens Eisenhofer).
|
||||
- handle _toExpr for quantified formulas in JS bindings
|
||||
|
@ -638,7 +638,7 @@ xor88, parno, gario, Bauna, GManNickG, hanwentao, dinu09, fhowar, Cici, chinissa
|
|||
(assert F)
|
||||
(check-sat a)
|
||||
(check-sat)
|
||||
If 'F' is unstatisfiable independently of the assumption 'a', and
|
||||
If 'F' is unsatisfiable independently of the assumption 'a', and
|
||||
the inconsistency can be detected by just performing propagation,
|
||||
Then, version <= 4.3.1 may return
|
||||
unsat
|
||||
|
|
|
@ -139,7 +139,7 @@ def mk_z3consts_py_internal(api_files, output_dir):
|
|||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
words = re.split('[^-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
|
@ -227,7 +227,7 @@ def mk_z3consts_dotnet_internal(api_files, output_dir):
|
|||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
words = re.split('[^-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
|
@ -315,7 +315,7 @@ def mk_z3consts_java_internal(api_files, package_name, output_dir):
|
|||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
words = re.split('[^-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
|
@ -441,7 +441,7 @@ def mk_z3consts_ml_internal(api_files, output_dir):
|
|||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
words = re.split('[^-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
|
@ -574,7 +574,7 @@ def mk_def_file_internal(defname, dll_name, export_header_files):
|
|||
for line in api:
|
||||
m = pat1.match(line)
|
||||
if m:
|
||||
words = re.split('\W+', line)
|
||||
words = re.split(r'\W+', line)
|
||||
i = 0
|
||||
for w in words:
|
||||
if w == 'Z3_API':
|
||||
|
@ -618,9 +618,9 @@ def mk_gparams_register_modules_internal(h_files_full_path, path):
|
|||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
fout.write('#include "util/gparams.h"\n')
|
||||
reg_pat = re.compile('[ \t]*REG_PARAMS\(\'([^\']*)\'\)')
|
||||
reg_mod_pat = re.compile('[ \t]*REG_MODULE_PARAMS\(\'([^\']*)\', *\'([^\']*)\'\)')
|
||||
reg_mod_descr_pat = re.compile('[ \t]*REG_MODULE_DESCRIPTION\(\'([^\']*)\', *\'([^\']*)\'\)')
|
||||
reg_pat = re.compile(r'[ \t]*REG_PARAMS\(\'([^\']*)\'\)')
|
||||
reg_mod_pat = re.compile(r'[ \t]*REG_MODULE_PARAMS\(\'([^\']*)\', *\'([^\']*)\'\)')
|
||||
reg_mod_descr_pat = re.compile(r'[ \t]*REG_MODULE_DESCRIPTION\(\'([^\']*)\', *\'([^\']*)\'\)')
|
||||
for h_file in sorted_headers_by_component(h_files_full_path):
|
||||
added_include = False
|
||||
with io.open(h_file, encoding='utf-8', mode='r') as fin:
|
||||
|
@ -698,9 +698,9 @@ def mk_install_tactic_cpp_internal(h_files_full_path, path):
|
|||
fout.write('#include "cmd_context/tactic_cmds.h"\n')
|
||||
fout.write('#include "cmd_context/simplifier_cmds.h"\n')
|
||||
fout.write('#include "cmd_context/cmd_context.h"\n')
|
||||
tactic_pat = re.compile('[ \t]*ADD_TACTIC\(.*\)')
|
||||
probe_pat = re.compile('[ \t]*ADD_PROBE\(.*\)')
|
||||
simplifier_pat = re.compile('[ \t]*ADD_SIMPLIFIER\(.*\)')
|
||||
tactic_pat = re.compile(r'[ \t]*ADD_TACTIC\(.*\)')
|
||||
probe_pat = re.compile(r'[ \t]*ADD_PROBE\(.*\)')
|
||||
simplifier_pat = re.compile(r'[ \t]*ADD_SIMPLIFIER\(.*\)')
|
||||
for h_file in sorted_headers_by_component(h_files_full_path):
|
||||
added_include = False
|
||||
try:
|
||||
|
@ -780,10 +780,10 @@ def mk_mem_initializer_cpp_internal(h_files_full_path, path):
|
|||
fullname = os.path.join(path, 'mem_initializer.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
initializer_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)')
|
||||
initializer_pat = re.compile(r'[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)')
|
||||
# ADD_INITIALIZER with priority
|
||||
initializer_prio_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)')
|
||||
finalizer_pat = re.compile('[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)')
|
||||
initializer_prio_pat = re.compile(r'[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)')
|
||||
finalizer_pat = re.compile(r'[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)')
|
||||
for h_file in sorted_headers_by_component(h_files_full_path):
|
||||
added_include = False
|
||||
with io.open(h_file, encoding='utf-8', mode='r') as fin:
|
||||
|
@ -952,7 +952,7 @@ def mk_hpp_from_pyg(pyg_file, output_dir):
|
|||
'UINT_MAX' : UINT_MAX,
|
||||
'max_memory_param' : max_memory_param,
|
||||
'max_steps_param' : max_steps_param,
|
||||
# Note that once this function is enterred that function
|
||||
# Note that once this function is entered that function
|
||||
# executes with respect to the globals of this module and
|
||||
# not the globals defined here
|
||||
'def_module_params' : def_module_params,
|
||||
|
|
|
@ -395,7 +395,7 @@ def check_java():
|
|||
else:
|
||||
# Search for jni.h in the library directories...
|
||||
t = open('errout', 'r')
|
||||
open_pat = re.compile("\[search path for class files: (.*)\]")
|
||||
open_pat = re.compile(r"\[search path for class files: (.*)\]")
|
||||
cdirs = []
|
||||
for line in t:
|
||||
m = open_pat.match(line)
|
||||
|
@ -812,8 +812,8 @@ def parse_options():
|
|||
def extract_c_includes(fname):
|
||||
result = {}
|
||||
# We look for well behaved #include directives
|
||||
std_inc_pat = re.compile("[ \t]*#include[ \t]*\"(.*)\"[ \t]*")
|
||||
system_inc_pat = re.compile("[ \t]*#include[ \t]*\<.*\>[ \t]*")
|
||||
std_inc_pat = re.compile(r"[ \t]*#include[ \t]*\"(.*)\"[ \t]*")
|
||||
system_inc_pat = re.compile(r"[ \t]*#include[ \t]*\<.*\>[ \t]*")
|
||||
# We should generate and error for any occurrence of #include that does not match the previous pattern.
|
||||
non_std_inc_pat = re.compile(".*#include.*")
|
||||
|
||||
|
@ -1720,7 +1720,7 @@ class DotNetDLLComponent(Component):
|
|||
|
||||
print("Version output to csproj:", version)
|
||||
|
||||
core_csproj_str = """<Project Sdk="Microsoft.NET.Sdk">
|
||||
core_csproj_str = r"""<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.4</TargetFramework>
|
||||
|
@ -2246,7 +2246,7 @@ class DotNetExampleComponent(ExampleComponent):
|
|||
else:
|
||||
platform = 'x86'
|
||||
|
||||
dotnet_proj_str = """<Project Sdk="Microsoft.NET.Sdk">
|
||||
dotnet_proj_str = r"""<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
@ -3162,7 +3162,7 @@ def mk_vs_proj_property_groups(f, name, target_ext, type):
|
|||
f.write(' <Keyword>Win32Proj</Keyword>\n')
|
||||
f.write(' <PlatformToolset>%s</PlatformToolset>\n' % get_platform_toolset_str())
|
||||
f.write(' </PropertyGroup>\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />\n')
|
||||
f.write(' <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'" Label="Configuration">\n')
|
||||
f.write(' <ConfigurationType>%s</ConfigurationType>\n' % type)
|
||||
f.write(' <CharacterSet>Unicode</CharacterSet>\n')
|
||||
|
@ -3173,24 +3173,24 @@ def mk_vs_proj_property_groups(f, name, target_ext, type):
|
|||
f.write(' <CharacterSet>Unicode</CharacterSet>\n')
|
||||
f.write(' <UseOfMfc>false</UseOfMfc>\n')
|
||||
f.write(' </PropertyGroup>\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />\n')
|
||||
f.write(' <ImportGroup Label="ExtensionSettings" />\n')
|
||||
f.write(' <ImportGroup Label="PropertySheets">\n')
|
||||
f.write(' <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" /> </ImportGroup>\n')
|
||||
f.write(' <Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" /> </ImportGroup>\n')
|
||||
f.write(' <PropertyGroup Label="UserMacros" />\n')
|
||||
f.write(' <PropertyGroup>\n')
|
||||
f.write(' <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">$(SolutionDir)\$(ProjectName)\$(Configuration)\</OutDir>\n')
|
||||
f.write(' <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">$(SolutionDir)\\$(ProjectName)\\$(Configuration)\\</OutDir>\n')
|
||||
f.write(' <TargetName Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">%s</TargetName>\n' % name)
|
||||
f.write(' <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">.%s</TargetExt>\n' % target_ext)
|
||||
f.write(' <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">$(SolutionDir)\$(ProjectName)\$(Configuration)\</OutDir>\n')
|
||||
f.write(' <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">$(SolutionDir)\\$(ProjectName)\\$(Configuration)\\</OutDir>\n')
|
||||
f.write(' <TargetName Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">%s</TargetName>\n' % name)
|
||||
f.write(' <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">.%s</TargetExt>\n' % target_ext)
|
||||
f.write(' </PropertyGroup>\n')
|
||||
f.write(' <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">\n')
|
||||
f.write(' <IntDir>$(ProjectName)\$(Configuration)\</IntDir>\n')
|
||||
f.write(' <IntDir>$(ProjectName)\\$(Configuration)\\</IntDir>\n')
|
||||
f.write(' </PropertyGroup>\n')
|
||||
f.write(' <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">\n')
|
||||
f.write(' <IntDir>$(ProjectName)\$(Configuration)\</IntDir>\n')
|
||||
f.write(' <IntDir>$(ProjectName)\\$(Configuration)\\</IntDir>\n')
|
||||
f.write(' </PropertyGroup>\n')
|
||||
|
||||
|
||||
|
@ -3267,7 +3267,7 @@ def mk_vs_proj(name, components):
|
|||
mk_vs_proj_link_exe(f, name, debug=False)
|
||||
f.write(' </ItemDefinitionGroup>\n')
|
||||
mk_vs_proj_dep_groups(f, name, components)
|
||||
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />\n')
|
||||
f.write(' <ImportGroup Label="ExtensionTargets">\n')
|
||||
f.write(' </ImportGroup>\n')
|
||||
f.write('</Project>\n')
|
||||
|
@ -3308,7 +3308,7 @@ def mk_vs_proj_dll(name, components):
|
|||
mk_vs_proj_link_dll(f, name, debug=False)
|
||||
f.write(' </ItemDefinitionGroup>\n')
|
||||
mk_vs_proj_dep_groups(f, name, components)
|
||||
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />\n')
|
||||
f.write(' <ImportGroup Label="ExtensionTargets">\n')
|
||||
f.write(' </ImportGroup>\n')
|
||||
f.write('</Project>\n')
|
||||
|
|
|
@ -116,8 +116,8 @@ class APITypes:
|
|||
|
||||
def def_Types(self, api_files):
|
||||
global Closures
|
||||
pat1 = re.compile(" *def_Type\(\'(.*)\',[^\']*\'(.*)\',[^\']*\'(.*)\'\)[ \t]*")
|
||||
pat2 = re.compile("Z3_DECLARE_CLOSURE\((.*),(.*), \((.*)\)\)")
|
||||
pat1 = re.compile(r" *def_Type\(\'(.*)\',[^\']*\'(.*)\',[^\']*\'(.*)\'\)[ \t]*")
|
||||
pat2 = re.compile(r"Z3_DECLARE_CLOSURE\((.*),(.*), \((.*)\)\)")
|
||||
for api_file in api_files:
|
||||
with open(api_file, 'r') as api:
|
||||
for line in api:
|
||||
|
|
|
@ -22,7 +22,7 @@ A tactic for performing Ackermann reduction for bit-vector formulas
|
|||
### Long Description
|
||||
|
||||
The Ackermann reduction replaces uninterpreted functions $f(t_1), f(t_2)$
|
||||
by fresh variables $f_1, f_2$ and addes axioms $t_1 \simeq t_2 \implies f_1 \simeq f_2$.
|
||||
by fresh variables $f_1, f_2$ and adds axioms $t_1 \simeq t_2 \implies f_1 \simeq f_2$.
|
||||
The reduction has the effect of eliminating uninterpreted functions. When the reduction
|
||||
produces a pure bit-vector benchmark, it allows Z3 to use a specialized SAT solver.
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ Revision History:
|
|||
|
||||
/** \brief
|
||||
Information about how a formula is being converted into
|
||||
a formula without uninterpreted function symbols via ackermannization.
|
||||
a formula without uninterpreted function symbols via ackermannization.
|
||||
|
||||
The intended use is that new terms are added via set_abstr.
|
||||
Once all terms are abstracted, call seal.
|
||||
|
|
|
@ -231,7 +231,7 @@ namespace api {
|
|||
void handle_exception(z3_exception & ex);
|
||||
char const * get_exception_msg() const { return m_exception_msg.c_str(); }
|
||||
|
||||
// Interrupt the current interruptable object
|
||||
// Interrupt the current interruptible object
|
||||
void interrupt();
|
||||
|
||||
void invoke_error_handler(Z3_error_code c);
|
||||
|
|
|
@ -742,7 +742,7 @@ extern "C" {
|
|||
fpa_util & fu = ctx->fpautil();
|
||||
if (!ctx->bvutil().is_bv(to_expr(bv)) ||
|
||||
!fu.is_float(to_sort(s))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, "bv sort the flaot sort expected");
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, "bv sort the float sort expected");
|
||||
return nullptr;
|
||||
}
|
||||
expr * a = fu.mk_to_fp(to_sort(s), to_expr(bv));
|
||||
|
|
|
@ -1092,15 +1092,15 @@ extern "C" {
|
|||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback s, unsigned num_fixed, Z3_ast const* fixed_ids, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq) {
|
||||
bool Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback s, unsigned num_fixed, Z3_ast const* fixed_ids, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_propagate_consequence(c, s, num_fixed, fixed_ids, num_eqs, eq_lhs, eq_rhs, conseq);
|
||||
RESET_ERROR_CODE();
|
||||
expr* const * _fixed_ids = (expr* const*) fixed_ids;
|
||||
expr* const * _eq_lhs = (expr*const*) eq_lhs;
|
||||
expr* const * _eq_rhs = (expr*const*) eq_rhs;
|
||||
reinterpret_cast<user_propagator::callback*>(s)->propagate_cb(num_fixed, _fixed_ids, num_eqs, _eq_lhs, _eq_rhs, to_expr(conseq));
|
||||
Z3_CATCH;
|
||||
return reinterpret_cast<user_propagator::callback*>(s)->propagate_cb(num_fixed, _fixed_ids, num_eqs, _eq_lhs, _eq_rhs, to_expr(conseq));
|
||||
Z3_CATCH_RETURN(false);
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_propagate_created(Z3_context c, Z3_solver s, Z3_created_eh created_eh) {
|
||||
|
|
|
@ -320,7 +320,7 @@ namespace z3 {
|
|||
/**
|
||||
\brief Create a recursive datatype over a single sort.
|
||||
\c name is the name of the recursive datatype
|
||||
\c n - the numer of constructors of the datatype
|
||||
\c n - the number of constructors of the datatype
|
||||
\c cs - the \c n constructors used to define the datatype
|
||||
|
||||
References to the datatype can be created using \ref datatype_sort.
|
||||
|
@ -4496,14 +4496,14 @@ namespace z3 {
|
|||
Z3_solver_propagate_consequence(ctx(), cb, fixed.size(), _fixed.ptr(), lhs.size(), _lhs.ptr(), _rhs.ptr(), conseq);
|
||||
}
|
||||
|
||||
void propagate(expr_vector const& fixed, expr const& conseq) {
|
||||
bool propagate(expr_vector const& fixed, expr const& conseq) {
|
||||
assert(cb);
|
||||
assert((Z3_context)conseq.ctx() == (Z3_context)ctx());
|
||||
array<Z3_ast> _fixed(fixed);
|
||||
Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
|
||||
return Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
|
||||
}
|
||||
|
||||
void propagate(expr_vector const& fixed,
|
||||
bool propagate(expr_vector const& fixed,
|
||||
expr_vector const& lhs, expr_vector const& rhs,
|
||||
expr const& conseq) {
|
||||
assert(cb);
|
||||
|
@ -4513,7 +4513,7 @@ namespace z3 {
|
|||
array<Z3_ast> _lhs(lhs);
|
||||
array<Z3_ast> _rhs(rhs);
|
||||
|
||||
Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), lhs.size(), _lhs.ptr(), _rhs.ptr(), conseq);
|
||||
return Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), lhs.size(), _lhs.ptr(), _rhs.ptr(), conseq);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3770,7 +3770,7 @@ namespace Microsoft.Z3
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a simplifie that applies <paramref name="t1"/> and
|
||||
/// Create a simplifier that applies <paramref name="t1"/> and
|
||||
/// then <paramref name="t2"/>.
|
||||
/// </summary>
|
||||
public Simplifier AndThen(Simplifier t1, Simplifier t2, params Simplifier[] ts)
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace Microsoft.Z3
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Symbols's hash code.
|
||||
/// The Symbol's hash code.
|
||||
/// </summary>
|
||||
/// <returns>A hash code</returns>
|
||||
public override int GetHashCode()
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace Microsoft.Z3
|
|||
public delegate void CreatedEh(Expr term);
|
||||
|
||||
/// <summary>
|
||||
/// Delegate type for callback into solver's branching. The values can be overriden by calling <see cref="NextSplit" />.
|
||||
/// Delegate type for callback into solver's branching. The values can be overridden by calling <see cref="NextSplit" />.
|
||||
/// </summary>
|
||||
/// <param name="term">A bit-vector or Boolean used for branching</param>
|
||||
/// <param name="idx">If the term is a bit-vector, then an index into the bit-vector being branched on</param>
|
||||
|
@ -252,11 +252,29 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Propagate consequence
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the propagated expression is new for the solver;
|
||||
/// <see langword="false" /> if the propagation was ignored
|
||||
/// </returns>
|
||||
/// </summary>
|
||||
public void Propagate(IEnumerable<Expr> terms, Expr conseq)
|
||||
public bool Propagate(IEnumerable<Expr> terms, Expr conseq)
|
||||
{
|
||||
return Propagate(terms, new EqualityPairs(), conseq);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Propagate consequence
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the propagated expression is new for the solver;
|
||||
/// <see langword="false" /> if the propagation was ignored
|
||||
/// </returns>
|
||||
/// </summary>
|
||||
public bool Propagate(IEnumerable<Expr> terms, EqualityPairs equalities, Expr conseq)
|
||||
{
|
||||
var nTerms = Z3Object.ArrayToNative(terms.ToArray());
|
||||
Native.Z3_solver_propagate_consequence(ctx.nCtx, this.callback, (uint)nTerms.Length, nTerms, 0u, null, null, conseq.NativeObject);
|
||||
var nLHS = Z3Object.ArrayToNative(equalities.LHS.ToArray());
|
||||
var nRHS = Z3Object.ArrayToNative(equalities.RHS.ToArray());
|
||||
return Native.Z3_solver_propagate_consequence(ctx.nCtx, this.callback, (uint)nTerms.Length, nTerms, (uint)equalities.Count, nLHS, nRHS, conseq.NativeObject) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -375,4 +393,72 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of equalities used as justifications for propagation
|
||||
/// </summary>
|
||||
public class EqualityPairs {
|
||||
|
||||
readonly List<Expr> lhsList = new List<Expr>();
|
||||
readonly List<Expr> rhsList = new List<Expr>();
|
||||
|
||||
/// <summary>
|
||||
/// The left hand sides of the equalities
|
||||
/// </summary>
|
||||
public Expr[] LHS => lhsList.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// The right hand sides of the equalities
|
||||
/// </summary>
|
||||
public Expr[] RHS => rhsList.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// The number of equalities
|
||||
/// </summary>
|
||||
public int Count => lhsList.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an equality to the list. The sorts of the arguments have to be the same.
|
||||
/// <param name="lhs">The left hand side of the equality</param>
|
||||
/// <param name="rhs">The right hand side of the equality</param>
|
||||
/// </summary>
|
||||
public void Add(Expr lhs, Expr rhs) {
|
||||
lhsList.Add(lhs);
|
||||
rhsList.Add(rhs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if two equality lists are equal.
|
||||
/// The function does not take symmetries, shuffling, or duplicates into account.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj) {
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
if (!(obj is EqualityPairs other))
|
||||
return false;
|
||||
if (lhsList.Count != other.lhsList.Count)
|
||||
return false;
|
||||
for (int i = 0; i < lhsList.Count; i++) {
|
||||
if (!lhsList[i].Equals(other.lhsList[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hash code for the list of equalities
|
||||
/// </summary>
|
||||
public override int GetHashCode() {
|
||||
int hash = lhsList.Count;
|
||||
unchecked {
|
||||
for (int i = 0; i < lhsList.Count; i++) {
|
||||
hash ^= lhsList[i].GetHashCode();
|
||||
hash *= 17;
|
||||
hash ^= rhsList[i].GetHashCode();
|
||||
hash *= 29;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2309,7 +2309,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Create the empty regular expression.
|
||||
* Coresponds to re.none
|
||||
* Corresponds to re.none
|
||||
*/
|
||||
public final <R extends Sort> ReExpr<R> mkEmptyRe(ReSort<R> s)
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.Map;
|
|||
*
|
||||
* <p><b>Mechanics: </b>once an object is created, a metadata is stored for it in
|
||||
* {@code referenceMap}, and a {@link PhantomReference} is created with a
|
||||
* reference to {@code referenceQueue}.
|
||||
* reference to {@code referenceQueue}.
|
||||
* Once the object becomes strongly unreachable, the phantom reference gets
|
||||
* added by JVM to the {@code referenceQueue}.
|
||||
* After each object creation, we iterate through the available objects in
|
||||
|
|
|
@ -226,6 +226,7 @@ DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateAdd(JNIEnv
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
DLL_VIS JNIEXPORT bool JNICALL Java_com_microsoft_z3_Native_propagateNextSplit(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, jlong e, long idx, int phase) {
|
||||
JavaInfo *info = (JavaInfo*)javainfo;
|
||||
Z3_solver_callback cb = info->cb;
|
||||
|
|
|
@ -166,7 +166,7 @@ public class Quantifier extends BoolExpr
|
|||
* @param sorts Sorts of bound variables.
|
||||
* @param names Names of bound variables
|
||||
* @param body Body of quantifier
|
||||
* @param weight Weight used to indicate priority for qunatifier instantiation
|
||||
* @param weight Weight used to indicate priority for quantifier instantiation
|
||||
* @param patterns Nullable patterns
|
||||
* @param noPatterns Nullable noPatterns
|
||||
* @param quantifierID Nullable quantifierID
|
||||
|
|
|
@ -13,7 +13,7 @@ Then run `npm i` to install dependencies, `npm run build:ts` to build the TypeSc
|
|||
|
||||
### Build on your own
|
||||
|
||||
Consult the file [build-wasm.ts](https://github.com/Z3Prover/z3/blob/master/src/api/js/scripts/build-wasm.ts) for configurations used for building wasm.
|
||||
Consult the file [build-wasm.ts](https://github.com/Z3Prover/z3/blob/master/src/api/js/scripts/build-wasm.ts) for configurations used for building wasm.
|
||||
|
||||
## Tests
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ for (let fn of functions) {
|
|||
param.sizeIndex = defParams[idx].sizeIndex;
|
||||
if (!param.isArray && param.isPtr) {
|
||||
// not clear why some things are written as `int * x` and others `int x[]`
|
||||
// but we can jsut cast
|
||||
// but we can just cast
|
||||
param.isArray = true;
|
||||
param.isPtr = false;
|
||||
}
|
||||
|
|
|
@ -223,7 +223,7 @@ correctly found by gcc.
|
|||
|
||||
I specifically left the cygwin part of the code intact as I have no
|
||||
idea what the original author meant by this, neither do I use or
|
||||
tested this patch in the cygwin or mingw environemt. I think that this
|
||||
tested this patch in the cygwin or mingw environment. I think that this
|
||||
code is rather outdated and shouldn't really work. E.g., in the
|
||||
--staticlib mode adding z3linkdep (which is libz3-static.a) as an
|
||||
argument to `ocamlmklib` will yield the following broken archive
|
||||
|
|
|
@ -292,7 +292,7 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
|||
distos = RELEASE_METADATA[2]
|
||||
if distos in ('debian', 'ubuntu'):
|
||||
raise Exception(
|
||||
"Linux binary distributions must be built on centos to conform to PEP 513 or alpine if targetting musl"
|
||||
"Linux binary distributions must be built on centos to conform to PEP 513 or alpine if targeting musl"
|
||||
)
|
||||
elif distos == 'glibc':
|
||||
if arch == 'x64':
|
||||
|
|
|
@ -5385,7 +5385,7 @@ def EnumSort(name, values, ctx=None):
|
|||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(isinstance(name, str), "Name must be a string")
|
||||
_z3_assert(all([isinstance(v, str) for v in values]), "Eumeration sort values must be strings")
|
||||
_z3_assert(all([isinstance(v, str) for v in values]), "Enumeration sort values must be strings")
|
||||
_z3_assert(len(values) > 0, "At least one value expected")
|
||||
ctx = _get_ctx(ctx)
|
||||
num = len(values)
|
||||
|
@ -11286,6 +11286,8 @@ def Plus(re):
|
|||
>>> print(simplify(InRe("", re)))
|
||||
False
|
||||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(is_expr(re), "expression expected")
|
||||
return ReRef(Z3_mk_re_plus(re.ctx_ref(), re.as_ast()), re.ctx)
|
||||
|
||||
|
||||
|
@ -11299,6 +11301,8 @@ def Option(re):
|
|||
>>> print(simplify(InRe("aa", re)))
|
||||
False
|
||||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(is_expr(re), "expression expected")
|
||||
return ReRef(Z3_mk_re_option(re.ctx_ref(), re.as_ast()), re.ctx)
|
||||
|
||||
|
||||
|
@ -11317,6 +11321,8 @@ def Star(re):
|
|||
>>> print(simplify(InRe("", re)))
|
||||
True
|
||||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(is_expr(re), "expression expected")
|
||||
return ReRef(Z3_mk_re_star(re.ctx_ref(), re.as_ast()), re.ctx)
|
||||
|
||||
|
||||
|
@ -11330,6 +11336,8 @@ def Loop(re, lo, hi=0):
|
|||
>>> print(simplify(InRe("", re)))
|
||||
False
|
||||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(is_expr(re), "expression expected")
|
||||
return ReRef(Z3_mk_re_loop(re.ctx_ref(), re.as_ast(), lo, hi), re.ctx)
|
||||
|
||||
|
||||
|
@ -11343,11 +11351,17 @@ def Range(lo, hi, ctx=None):
|
|||
"""
|
||||
lo = _coerce_seq(lo, ctx)
|
||||
hi = _coerce_seq(hi, ctx)
|
||||
if z3_debug():
|
||||
_z3_assert(is_expr(lo), "expression expected")
|
||||
_z3_assert(is_expr(hi), "expression expected")
|
||||
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 expression
|
||||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(is_expr(a), "expression expected")
|
||||
_z3_assert(is_expr(b), "expression expected")
|
||||
return ReRef(Z3_mk_re_diff(a.ctx_ref(), a.ast, b.ast), a.ctx)
|
||||
|
||||
def AllChar(regex_sort, ctx=None):
|
||||
|
@ -11690,7 +11704,7 @@ class UserPropagateBase:
|
|||
num_eqs = len(eqs)
|
||||
_lhs, _num_lhs = _to_ast_array([x for x, y in eqs])
|
||||
_rhs, _num_rhs = _to_ast_array([y for x, y in eqs])
|
||||
Z3_solver_propagate_consequence(e.ctx.ref(), ctypes.c_void_p(
|
||||
return Z3_solver_propagate_consequence(e.ctx.ref(), ctypes.c_void_p(
|
||||
self.cb), num_fixed, _ids, num_eqs, _lhs, _rhs, e.ast)
|
||||
|
||||
def conflict(self, deps = [], eqs = []):
|
||||
|
|
|
@ -275,7 +275,7 @@ def prove(claim, assume=None, verbose=0):
|
|||
|
||||
def get_models(f, k):
|
||||
"""
|
||||
Returns the first k models satisfiying f.
|
||||
Returns the first k models satisfying f.
|
||||
If f is not satisfiable, returns False.
|
||||
If f cannot be solved, returns None
|
||||
If f is satisfiable, returns the first k models
|
||||
|
@ -485,7 +485,7 @@ def model_str(m, as_str=True):
|
|||
x = 10, y = 3
|
||||
|
||||
EXAMPLES:
|
||||
see doctest exampels from function prove()
|
||||
see doctest examples from function prove()
|
||||
|
||||
"""
|
||||
if z3_debug():
|
||||
|
|
|
@ -2172,7 +2172,7 @@ extern "C" {
|
|||
\brief Query constructor for declared functions.
|
||||
|
||||
\param c logical context.
|
||||
\param constr constructor container. The container must have been passed in to a #Z3_mk_datatype call.
|
||||
\param constr constructor container. The container must have been passed into a #Z3_mk_datatype call.
|
||||
\param num_fields number of accessor fields in the constructor.
|
||||
\param constructor constructor function declaration, allocated by user.
|
||||
\param tester constructor test function declaration, allocated by user.
|
||||
|
@ -2317,7 +2317,7 @@ extern "C" {
|
|||
\param args constants that are used as arguments to the recursive function in the definition.
|
||||
\param body body of the recursive function
|
||||
|
||||
After declaring a recursive function or a collection of mutually recursive functions, use
|
||||
After declaring a recursive function or a collection of mutually recursive functions, use
|
||||
this function to provide the definition for the recursive function.
|
||||
|
||||
\sa Z3_mk_rec_func_decl
|
||||
|
@ -3614,7 +3614,7 @@ extern "C" {
|
|||
|
||||
/**
|
||||
\brief Retrieve the string constant stored in \c s.
|
||||
Characters outside the basic printiable ASCII range are escaped.
|
||||
Characters outside the basic printable ASCII range are escaped.
|
||||
|
||||
\pre Z3_is_string(c, s)
|
||||
|
||||
|
@ -4897,7 +4897,7 @@ extern "C" {
|
|||
/**
|
||||
\brief Return a hash code for the given AST.
|
||||
The hash code is structural but two different AST objects can map to the same hash.
|
||||
The result of \c Z3_get_ast_id returns an indentifier that is unique over the
|
||||
The result of \c Z3_get_ast_id returns an identifier that is unique over the
|
||||
set of live AST objects.
|
||||
|
||||
def_API('Z3_get_ast_hash', UINT, (_in(CONTEXT), _in(AST)))
|
||||
|
@ -5346,7 +5346,7 @@ extern "C" {
|
|||
Z3_ast const to[]);
|
||||
|
||||
/**
|
||||
\brief Substitute funcions in \c from with new expressions in \c to.
|
||||
\brief Substitute functions in \c from with new expressions in \c to.
|
||||
|
||||
The expressions in \c to can have free variables. The free variable in \c to at index 0
|
||||
refers to the first argument of \c from, the free variable at index 1 corresponds to the second argument.
|
||||
|
@ -7026,13 +7026,13 @@ extern "C" {
|
|||
Z3_on_clause_eh on_clause_eh);
|
||||
|
||||
/**
|
||||
\brief register a user-properator with the solver.
|
||||
\brief register a user-propagator with the solver.
|
||||
|
||||
\param c - context.
|
||||
\param s - solver object.
|
||||
\param user_context - a context used to maintain state for callbacks.
|
||||
\param push_eh - a callback invoked when scopes are pushed
|
||||
\param pop_eh - a callback invoked when scopes are poped
|
||||
\param pop_eh - a callback invoked when scopes are popped
|
||||
\param fresh_eh - a solver may spawn new solvers internally. This callback is used to produce a fresh user_context to be associated with fresh solvers.
|
||||
|
||||
def_API('Z3_solver_propagate_init', VOID, (_in(CONTEXT), _in(SOLVER), _in(VOID_PTR), _fnptr(Z3_push_eh), _fnptr(Z3_pop_eh), _fnptr(Z3_fresh_eh)))
|
||||
|
@ -7147,14 +7147,18 @@ extern "C" {
|
|||
|
||||
/**
|
||||
\brief propagate a consequence based on fixed values.
|
||||
This is a callback a client may invoke during the fixed_eh callback.
|
||||
This is a callback a client may invoke during the fixed_eh callback.
|
||||
The callback adds a propagation consequence based on the fixed values of the
|
||||
\c ids.
|
||||
|
||||
def_API('Z3_solver_propagate_consequence', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, AST), _in(UINT), _in_array(4, AST), _in_array(4, AST), _in(AST)))
|
||||
\c ids.
|
||||
The solver might discard the propagation in case it is true in the current state.
|
||||
The function returns false in this case; otw. the function returns true.
|
||||
At least one propagation in the final callback has to return true in order to
|
||||
prevent the solver from finishing.
|
||||
|
||||
def_API('Z3_solver_propagate_consequence', BOOL, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, AST), _in(UINT), _in_array(4, AST), _in_array(4, AST), _in(AST)))
|
||||
*/
|
||||
|
||||
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback cb, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
|
||||
|
||||
bool Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback cb, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
|
||||
|
||||
/**
|
||||
\brief Check whether the assertions in a given solver are consistent or not.
|
||||
|
|
|
@ -72,7 +72,7 @@ struct z3_replayer::imp {
|
|||
|
||||
void check_arg(unsigned pos, value_kind k) const {
|
||||
if (pos >= m_args.size()) {
|
||||
TRACE("z3_replayer", tout << "too few arguments " << m_args.size() << " expecting " << kind2string(k) << "\n";);
|
||||
TRACE("z3_replayer", tout << pos << " too few arguments " << m_args.size() << " expecting " << kind2string(k) << "\n";);
|
||||
throw z3_replayer_exception("invalid argument reference");
|
||||
}
|
||||
if (m_args[pos].m_kind != k) {
|
||||
|
|
|
@ -370,7 +370,7 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
|
|||
if (is_real) {
|
||||
return m_manager->mk_func_decl(symbol("^0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_POWER0));
|
||||
}
|
||||
return m_manager->mk_func_decl(symbol("^0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_POWER0));
|
||||
return m_manager->mk_func_decl(symbol("^0"), m_int_decl, m_int_decl, m_real_decl, func_decl_info(m_family_id, OP_POWER0));
|
||||
case OP_TO_REAL: return m_to_real_decl;
|
||||
case OP_TO_INT: return m_to_int_decl;
|
||||
case OP_IS_INT: return m_is_int_decl;
|
||||
|
@ -834,7 +834,7 @@ bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* con
|
|||
func_decl* arith_util::mk_ipower0() {
|
||||
sort* s = mk_int();
|
||||
sort* rs[2] = { s, s };
|
||||
return m_manager.mk_func_decl(arith_family_id, OP_POWER0, 0, nullptr, 2, rs, s);
|
||||
return m_manager.mk_func_decl(arith_family_id, OP_POWER0, 0, nullptr, 2, rs, mk_real());
|
||||
}
|
||||
|
||||
func_decl* arith_util::mk_rpower0() {
|
||||
|
|
|
@ -1378,6 +1378,7 @@ void ast_manager::init() {
|
|||
ENSURE(model_value_family_id == mk_family_id("model-value"));
|
||||
ENSURE(user_sort_family_id == mk_family_id("user-sort"));
|
||||
ENSURE(arith_family_id == mk_family_id("arith"));
|
||||
ENSURE(poly_family_id == mk_family_id("polymorphic"));
|
||||
basic_decl_plugin * plugin = alloc(basic_decl_plugin);
|
||||
register_plugin(basic_family_id, plugin);
|
||||
m_bool_sort = plugin->mk_bool_sort();
|
||||
|
@ -2019,6 +2020,11 @@ sort * ast_manager::mk_uninterpreted_sort(symbol const & name, unsigned num_para
|
|||
return plugin->mk_sort(kind, num_parameters, parameters);
|
||||
}
|
||||
|
||||
sort * ast_manager::mk_type_var(symbol const& name) {
|
||||
sort_info si(poly_family_id, 0);
|
||||
return mk_sort(name, &si);
|
||||
}
|
||||
|
||||
func_decl * ast_manager::mk_func_decl(symbol const & name, unsigned arity, sort * const * domain, sort * range,
|
||||
bool assoc, bool comm, bool inj) {
|
||||
func_decl_info info(null_family_id, null_decl_kind);
|
||||
|
|
|
@ -85,6 +85,7 @@ const family_id user_sort_family_id = 4;
|
|||
const family_id last_builtin_family_id = 4;
|
||||
|
||||
const family_id arith_family_id = 5;
|
||||
const family_id poly_family_id = 6;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -622,6 +623,7 @@ public:
|
|||
sort_size const & get_num_elements() const { return get_info()->get_num_elements(); }
|
||||
void set_num_elements(sort_size const& s) { get_info()->set_num_elements(s); }
|
||||
unsigned get_size() const { return get_obj_size(); }
|
||||
bool is_type_var() const { return get_family_id() == poly_family_id; }
|
||||
};
|
||||
|
||||
// -----------------------------------
|
||||
|
@ -1709,6 +1711,8 @@ public:
|
|||
|
||||
sort * mk_uninterpreted_sort(symbol const & name) { return mk_uninterpreted_sort(name, 0, nullptr); }
|
||||
|
||||
sort * mk_type_var(symbol const& name);
|
||||
|
||||
sort * mk_sort(symbol const & name, sort_info const & info) {
|
||||
if (info.get_family_id() == null_family_id) {
|
||||
return mk_uninterpreted_sort(name);
|
||||
|
|
|
@ -651,7 +651,7 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (args[i]->get_sort() != r->get_domain(i)) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " has sort " << mk_pp(args[i]->get_sort(), m) << " it does does not match declaration " << mk_pp(r, m);
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " has sort " << mk_pp(args[i]->get_sort(), m) << " it does not match declaration " << mk_pp(r, m);
|
||||
m.raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ enum bv_op_kind {
|
|||
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_BSDIV_OVFL, // signed division overflow predicate
|
||||
|
||||
OP_BNEG_OVFL, // negation overflow predicate
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
char_plugin for unicode suppport
|
||||
char_plugin for unicode support
|
||||
|
||||
Author:
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
char_plugin for unicode suppport
|
||||
char_plugin for unicode support
|
||||
|
||||
Author:
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
*
|
||||
* x = t -> fresh
|
||||
* x := if(fresh, t, diff(t))
|
||||
* where diff is a diagnonalization function available in domains of size > 1.
|
||||
* where diff is a diagonalization function available in domains of size > 1.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -807,7 +807,7 @@ bool iexpr_inverter::uncnstr(unsigned num, expr * const * args) const {
|
|||
|
||||
/**
|
||||
\brief Create a fresh variable for abstracting (f args[0] ... args[num-1])
|
||||
Return true if it a new variable was created, and false if the variable already existed for this
|
||||
Return true if a new variable was created, and false if the variable already existed for this
|
||||
application. Store the variable in v
|
||||
*/
|
||||
void iexpr_inverter::mk_fresh_uncnstr_var_for(sort * s, expr_ref & v) {
|
||||
|
|
|
@ -275,7 +275,7 @@ namespace datatype {
|
|||
}
|
||||
parameter const & name = parameters[0];
|
||||
if (!name.is_symbol()) {
|
||||
TRACE("datatype", tout << "expected symol parameter at position " << 0 << " got: " << name << "\n";);
|
||||
TRACE("datatype", tout << "expected symbol parameter at position " << 0 << " got: " << name << "\n";);
|
||||
throw invalid_datatype();
|
||||
}
|
||||
for (unsigned i = 1; i < num_parameters; ++i) {
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace datatype {
|
|||
class accessor {
|
||||
symbol m_name;
|
||||
sort_ref m_range;
|
||||
unsigned m_index; // reference to recursive data-type may only get resolved after all mutually recursive data-types are procssed.
|
||||
unsigned m_index; // reference to recursive data-type may only get resolved after all mutually recursive data-types are processed.
|
||||
constructor* m_constructor{ nullptr };
|
||||
public:
|
||||
accessor(ast_manager& m, symbol const& n, sort* range):
|
||||
|
|
|
@ -19,7 +19,7 @@ Notes:
|
|||
- data structures form the (legacy) SMT solver.
|
||||
- it still uses eager path compression.
|
||||
|
||||
NB. The worklist is in reality inheritied from the legacy SMT solver.
|
||||
NB. The worklist is in reality inherited from the legacy SMT solver.
|
||||
It is claimed to have the same effect as delayed congruence table reconstruction from egg.
|
||||
Similar to the legacy solver, parents are partially deduplicated.
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ Author:
|
|||
Notes:
|
||||
|
||||
- congruence closure justifications are given a timestamp so it is easy to sort them.
|
||||
See the longer descriptoin in euf_proof_checker.cpp
|
||||
See the longer description in euf_proof_checker.cpp
|
||||
|
||||
--*/
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, bool deps_valid, expr_de
|
|||
// functions introduced within macros are Skolem functions
|
||||
// To avoid unsound expansion of these as macros (because they
|
||||
// appear in model conversions and are therefore not fully
|
||||
// replacable) we prevent these from being treated as macro functions.
|
||||
// replaceable) we prevent these from being treated as macro functions.
|
||||
if (m_macro_manager.contains(f) || f->is_skolem())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ Revision History:
|
|||
where T[X] does not contain f.
|
||||
|
||||
This class is responsible for storing macros and expanding them.
|
||||
It has support for backtracking and tagging declarations in an expression as forbidded for being macros.
|
||||
It has support for backtracking and tagging declarations in an expression as forbidden for being macros.
|
||||
*/
|
||||
class macro_manager {
|
||||
ast_manager & m;
|
||||
|
|
|
@ -207,7 +207,7 @@ void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var
|
|||
// the instantiation rules for store(a, i, v) are:
|
||||
// store(a, i, v)[j] = if i = j then v else a[j] with patterns {a[j], store(a, i, v)} { store(a, i, v)[j] }
|
||||
// The first pattern is not included.
|
||||
// TBD use a model-based scheme for exracting instantiations instead of
|
||||
// TBD use a model-based scheme for extracting instantiations instead of
|
||||
// using multi-patterns.
|
||||
//
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ pattern_inference_cfg::pattern_inference_cfg(ast_manager & m, pattern_inference_
|
|||
m_le(),
|
||||
m_nested_arith_only(true),
|
||||
m_block_loop_patterns(params.m_pi_block_loop_patterns),
|
||||
m_decompose_patterns(params.m_pi_decompose_patterns),
|
||||
m_candidates(m),
|
||||
m_pattern_weight_lt(m_candidates_info),
|
||||
m_collect(m, *this),
|
||||
|
@ -407,6 +408,9 @@ bool pattern_inference_cfg::pattern_weight_lt::operator()(expr * n1, expr * n2)
|
|||
|
||||
|
||||
app* pattern_inference_cfg::mk_pattern(app* candidate) {
|
||||
if (!m_decompose_patterns)
|
||||
return m.mk_pattern(candidate);
|
||||
|
||||
auto has_var_arg = [&](expr* e) {
|
||||
if (!is_app(e))
|
||||
return false;
|
||||
|
|
|
@ -20,6 +20,7 @@ Revision History:
|
|||
|
||||
#include "ast/ast.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "params/pattern_inference_params.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/uint_set.h"
|
||||
|
@ -69,6 +70,7 @@ class pattern_inference_cfg : public default_rewriter_cfg {
|
|||
expr * const * m_no_patterns;
|
||||
bool m_nested_arith_only;
|
||||
bool m_block_loop_patterns;
|
||||
bool m_decompose_patterns;
|
||||
|
||||
struct info {
|
||||
uint_set m_free_vars;
|
||||
|
|
|
@ -260,7 +260,7 @@ class reduce_hypotheses {
|
|||
{ cls.push_back(cls_fact->get_arg(i)); }
|
||||
} else { cls.push_back(cls_fact); }
|
||||
|
||||
// construct new resovent
|
||||
// construct new resolvent
|
||||
ptr_buffer<expr> new_fact_cls;
|
||||
bool found;
|
||||
// XXX quadratic
|
||||
|
@ -604,7 +604,7 @@ public:
|
|||
// -- otherwise, the fact has not changed. nothing to simplify
|
||||
SASSERT(m.get_fact(tmp) == m.get_fact(m.get_parent(p, i)));
|
||||
parents.push_back(tmp);
|
||||
// remember that we have this derivation while we have not poped the trail
|
||||
// remember that we have this derivation while we have not popped the trail
|
||||
// but only if the proof is closed (i.e., a real unit)
|
||||
if (is_closed(tmp) && !m_units.contains(m.get_fact(tmp))) {
|
||||
m_units.insert(m.get_fact(tmp), tmp);
|
||||
|
|
|
@ -1121,7 +1121,7 @@ bool arith_rewriter::divides(expr* num, expr* den, expr_ref& result) {
|
|||
if (m_util.is_numeral(arg, num_r)) num_e = arg;
|
||||
}
|
||||
for (expr* arg : args2) {
|
||||
// dont remove divisor on (div (* -1 x) (* -1 y)) because rewriting would diverge.
|
||||
// don't remove divisor on (div (* -1 x) (* -1 y)) because rewriting would diverge.
|
||||
if (mark.is_marked(arg) && (!m_util.is_numeral(arg, num_r) || !num_r.is_minus_one())) {
|
||||
result = remove_divisor(arg, num, den);
|
||||
return true;
|
||||
|
@ -1569,21 +1569,48 @@ br_status arith_rewriter::mk_to_real_core(expr * arg, expr_ref & result) {
|
|||
}
|
||||
|
||||
br_status arith_rewriter::mk_is_int(expr * arg, expr_ref & result) {
|
||||
numeral a;
|
||||
if (m_util.is_numeral(arg, a)) {
|
||||
result = a.is_int() ? m.mk_true() : m.mk_false();
|
||||
numeral n;
|
||||
|
||||
if (m_util.is_numeral(arg, n)) {
|
||||
result = n.is_int() ? m.mk_true() : m.mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (m_util.is_to_real(arg)) {
|
||||
|
||||
if (m_util.is_to_real(arg)) {
|
||||
result = m.mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m.mk_eq(m.mk_app(get_fid(), OP_TO_REAL,
|
||||
m.mk_app(get_fid(), OP_TO_INT, arg)),
|
||||
arg);
|
||||
return BR_REWRITE3;
|
||||
|
||||
ptr_buffer<expr> todo;
|
||||
todo.push_back(arg);
|
||||
expr_fast_mark1 mark;
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
expr* e = todo[i];
|
||||
if (mark.is_marked(e))
|
||||
continue;
|
||||
mark.mark(e, true);
|
||||
if (m_util.is_to_real(e))
|
||||
continue;
|
||||
if (m_util.is_numeral(e, n)) {
|
||||
if (n.is_int())
|
||||
continue;
|
||||
goto bail;
|
||||
}
|
||||
if (m_util.is_mul(e) || m_util.is_add(e) || m_util.is_sub(e) || m_util.is_uminus(e)) {
|
||||
for (expr* a : *to_app(e))
|
||||
todo.push_back(a);
|
||||
continue;
|
||||
}
|
||||
goto bail;
|
||||
}
|
||||
result = m.mk_true();
|
||||
return BR_DONE;
|
||||
|
||||
bail:
|
||||
result = m.mk_eq(m.mk_app(get_fid(), OP_TO_REAL,
|
||||
m.mk_app(get_fid(), OP_TO_INT, arg)),
|
||||
arg);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
br_status arith_rewriter::mk_abs_core(expr * arg, expr_ref & result) {
|
||||
|
@ -1592,7 +1619,7 @@ br_status arith_rewriter::mk_abs_core(expr * arg, expr_ref & result) {
|
|||
}
|
||||
|
||||
|
||||
// Return true if t is of the form c*Pi where c is a numeral.
|
||||
// Return true if t is of the form c*Pi where c is a numeral.
|
||||
// Store c into k
|
||||
bool arith_rewriter::is_pi_multiple(expr * t, rational & k) {
|
||||
if (m_util.is_pi(t)) {
|
||||
|
@ -1603,7 +1630,7 @@ bool arith_rewriter::is_pi_multiple(expr * t, rational & k) {
|
|||
return m_util.is_mul(t, a, b) && m_util.is_pi(b) && m_util.is_numeral(a, k);
|
||||
}
|
||||
|
||||
// Return true if t is of the form (+ s c*Pi) where c is a numeral.
|
||||
// Return true if t is of the form (+ s c*Pi) where c is a numeral.
|
||||
// Store c into k, and c*Pi into m.
|
||||
bool arith_rewriter::is_pi_offset(expr * t, rational & k, expr * & m) {
|
||||
if (m_util.is_add(t)) {
|
||||
|
@ -1916,7 +1943,7 @@ br_status arith_rewriter::mk_tan_core(expr * arg, expr_ref & result) {
|
|||
br_status arith_rewriter::mk_asin_core(expr * arg, expr_ref & result) {
|
||||
// Remark: we assume that ForAll x : asin(-x) == asin(x).
|
||||
// Mathematica uses this as an axiom. Although asin is an underspecified function for x < -1 or x > 1.
|
||||
// Actually, in Mathematica, asin(x) is a total function that returns a complex number fo x < -1 or x > 1.
|
||||
// Actually, in Mathematica, asin(x) is a total function that returns a complex number for x < -1 or x > 1.
|
||||
rational k;
|
||||
if (is_numeral(arg, k)) {
|
||||
if (k.is_zero()) {
|
||||
|
|
|
@ -26,6 +26,7 @@ Notes:
|
|||
void bool_rewriter::updt_params(params_ref const & _p) {
|
||||
bool_rewriter_params p(_p);
|
||||
m_flat_and_or = p.flat_and_or();
|
||||
m_sort_disjunctions = p.sort_disjunctions();
|
||||
m_elim_and = p.elim_and();
|
||||
m_elim_ite = p.elim_ite();
|
||||
m_local_ctx = p.local_ctx();
|
||||
|
@ -183,7 +184,7 @@ br_status bool_rewriter::mk_flat_and_core(unsigned num_args, expr * const * args
|
|||
}
|
||||
|
||||
br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
bool s = false;
|
||||
bool s = false; // whether we have canceled some disjuncts or found some out or order
|
||||
ptr_buffer<expr> buffer;
|
||||
expr_fast_mark1 neg_lits;
|
||||
expr_fast_mark2 pos_lits;
|
||||
|
@ -292,8 +293,10 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args
|
|||
return st;
|
||||
#endif
|
||||
if (s) {
|
||||
ast_lt lt;
|
||||
std::sort(buffer.begin(), buffer.end(), lt);
|
||||
if (m_sort_disjunctions) {
|
||||
ast_lt lt;
|
||||
std::sort(buffer.begin(), buffer.end(), lt);
|
||||
}
|
||||
result = m().mk_or(sz, buffer.data());
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -329,7 +332,7 @@ br_status bool_rewriter::mk_flat_or_core(unsigned num_args, expr * const * args,
|
|||
}
|
||||
}
|
||||
if (mk_nflat_or_core(flat_args.size(), flat_args.data(), result) == BR_FAILED) {
|
||||
if (!ordered) {
|
||||
if (m_sort_disjunctions && !ordered) {
|
||||
ast_lt lt;
|
||||
std::sort(flat_args.begin(), flat_args.end(), lt);
|
||||
}
|
||||
|
@ -662,12 +665,19 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
SASSERT(m().is_value(val));
|
||||
|
||||
if (m().are_distinct(val, e)) {
|
||||
mk_eq(t, val, result);
|
||||
if (get_depth(t) < 500)
|
||||
mk_eq(t, val, result);
|
||||
else
|
||||
result = m().mk_eq(t, val);
|
||||
|
||||
result = m().mk_and(result, cond);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_distinct(val, t)) {
|
||||
mk_eq(e, val, result);
|
||||
if (get_depth(e) < 500)
|
||||
mk_eq(e, val, result);
|
||||
else
|
||||
result = m().mk_eq(e, val);
|
||||
result = m().mk_and(result, m().mk_not(cond));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ class bool_rewriter {
|
|||
ast_manager & m_manager;
|
||||
hoist_rewriter m_hoist;
|
||||
bool m_flat_and_or = false;
|
||||
bool m_sort_disjunctions = true;
|
||||
bool m_local_ctx = false;
|
||||
bool m_elim_and = false;
|
||||
bool m_blast_distinct = false;
|
||||
|
|
|
@ -307,7 +307,7 @@ namespace euf {
|
|||
}
|
||||
};
|
||||
SASSERT(e);
|
||||
if (num_scopes() > 0)
|
||||
if (num_scopes() > 0 && m_canonical.size() > n->get_id())
|
||||
m_trail.push(vtrail(m_canonical, n->get_id()));
|
||||
m_canonical.setx(n->get_id(), e);
|
||||
m_epochs.setx(n->get_id(), m_epoch, 0);
|
||||
|
|
|
@ -1394,14 +1394,13 @@ void cmd_context::reset_macros() {
|
|||
}
|
||||
|
||||
void cmd_context::reset_cmds() {
|
||||
for (auto& kv : m_cmds) {
|
||||
kv.m_value->reset(*this);
|
||||
for (auto& [k,v] : m_cmds) {
|
||||
v->reset(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_context::finalize_cmds() {
|
||||
for (auto& kv : m_cmds) {
|
||||
cmd * c = kv.m_value;
|
||||
for (auto& [k,c] : m_cmds) {
|
||||
c->finalize(*this);
|
||||
dealloc(c);
|
||||
}
|
||||
|
@ -1433,6 +1432,7 @@ void cmd_context::reset(bool finalize) {
|
|||
m_builtin_decls.reset();
|
||||
m_extra_builtin_decls.reset();
|
||||
m_check_logic.reset();
|
||||
m_proof_cmds = nullptr;
|
||||
reset_object_refs();
|
||||
reset_cmds();
|
||||
reset_psort_decls();
|
||||
|
|
|
@ -43,6 +43,7 @@ Proof checker for clauses created during search.
|
|||
#include "util/small_object_allocator.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "smt/smt_solver.h"
|
||||
#include "sat/sat_solver.h"
|
||||
#include "sat/sat_drat.h"
|
||||
|
@ -63,6 +64,7 @@ class proof_trim {
|
|||
vector<expr_ref_vector> m_clauses;
|
||||
bool_vector m_is_infer;
|
||||
symbol m_rup;
|
||||
bool m_empty = false;
|
||||
|
||||
void mk_clause(expr_ref_vector const& clause) {
|
||||
trim.init_clause();
|
||||
|
@ -121,25 +123,32 @@ public:
|
|||
*/
|
||||
|
||||
void infer(expr_ref_vector const& clause, app* hint) {
|
||||
if (m_empty)
|
||||
return;
|
||||
|
||||
if (hint && !is_rup(hint) && m_checker.check(hint)) {
|
||||
auto clause1 = m_checker.clause(hint);
|
||||
if (clause1.size() != clause.size()) {
|
||||
mk_clause(clause1);
|
||||
trim.assume(m_clauses.size());
|
||||
clause1.push_back(hint);
|
||||
trim.assume(m_clauses.size());
|
||||
m_clauses.push_back(clause1);
|
||||
m_is_infer.push_back(true);
|
||||
mk_clause(clause);
|
||||
trim.infer(m_clauses.size());
|
||||
m_clauses.push_back(clause);
|
||||
m_clauses.back().push_back(hint);
|
||||
m_is_infer.push_back(true);
|
||||
if (clause.empty())
|
||||
|
||||
if (clause.empty()) {
|
||||
mk_clause(clause);
|
||||
trim.infer(m_clauses.size());
|
||||
m_clauses.push_back(clause);
|
||||
m_clauses.back().push_back(hint);
|
||||
m_is_infer.push_back(true);
|
||||
m_empty = true;
|
||||
do_trim(std::cout);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mk_clause(clause);
|
||||
if (is_rup(hint))
|
||||
trim.infer(m_clauses.size());
|
||||
|
@ -149,20 +158,32 @@ public:
|
|||
if (hint)
|
||||
m_clauses.back().push_back(hint);
|
||||
m_is_infer.push_back(true);
|
||||
if (clause.empty())
|
||||
if (clause.empty()) {
|
||||
m_empty = true;
|
||||
do_trim(std::cout);
|
||||
}
|
||||
}
|
||||
|
||||
void updt_params(params_ref const& p) {
|
||||
trim.updt_params(p);
|
||||
}
|
||||
|
||||
expr_ref mk_dep(unsigned id, unsigned_vector const& deps) {
|
||||
arith_util a(m);
|
||||
expr_ref_vector args(m);
|
||||
args.push_back(a.mk_int(id));
|
||||
for (auto d : deps)
|
||||
args.push_back(a.mk_int(d));
|
||||
return expr_ref(m.mk_app(symbol("deps"), args.size(), args.data(), m.mk_proof_sort()), m);
|
||||
}
|
||||
|
||||
void do_trim(std::ostream& out) {
|
||||
ast_pp_util pp(m);
|
||||
auto ids = trim.trim();
|
||||
for (unsigned id : ids) {
|
||||
auto const& clause = m_clauses[id];
|
||||
for (auto const& [id, deps] : ids) {
|
||||
auto& clause = m_clauses[id];
|
||||
bool is_infer = m_is_infer[id];
|
||||
clause.push_back(mk_dep(id, deps));
|
||||
for (expr* e : clause)
|
||||
pp.collect(e);
|
||||
|
||||
|
@ -258,8 +279,12 @@ public:
|
|||
}
|
||||
|
||||
void add_literal(expr* e) override {
|
||||
if (m.is_proof(e))
|
||||
m_proof_hint = to_app(e);
|
||||
if (m.is_proof(e)) {
|
||||
if (!m_proof_hint)
|
||||
m_proof_hint = to_app(e);
|
||||
}
|
||||
else if (!m.is_bool(e))
|
||||
throw default_exception("literal should be either a Proof or Bool");
|
||||
else
|
||||
m_lits.push_back(e);
|
||||
}
|
||||
|
|
|
@ -348,6 +348,26 @@ std::ostream& psort_user_decl::display(std::ostream & out) const {
|
|||
return out << ")";
|
||||
}
|
||||
|
||||
// -------------------
|
||||
// psort_type_var_decl
|
||||
|
||||
psort_type_var_decl::psort_type_var_decl(unsigned id, pdecl_manager & m, symbol const & n):
|
||||
psort_decl(id, 0, m, n) {
|
||||
m_psort_kind = PSORT_TV;
|
||||
}
|
||||
|
||||
void psort_type_var_decl::finalize(pdecl_manager & m) {
|
||||
psort_decl::finalize(m);
|
||||
}
|
||||
|
||||
sort * psort_type_var_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
|
||||
return m.m().mk_type_var(m_name);
|
||||
}
|
||||
|
||||
std::ostream& psort_type_var_decl::display(std::ostream & out) const {
|
||||
return out << "(declare-type-var " << m_name << ")";
|
||||
}
|
||||
|
||||
// -------------------
|
||||
// psort_dt_decl
|
||||
|
||||
|
@ -969,6 +989,10 @@ psort_decl * pdecl_manager::mk_psort_dt_decl(unsigned num_params, symbol const &
|
|||
return new (a().allocate(sizeof(psort_dt_decl))) psort_dt_decl(m_id_gen.mk(), num_params, *this, n);
|
||||
}
|
||||
|
||||
psort_decl * pdecl_manager::mk_psort_type_var_decl(symbol const & n) {
|
||||
return new (a().allocate(sizeof(psort_type_var_decl))) psort_type_var_decl(m_id_gen.mk(), *this, n);
|
||||
}
|
||||
|
||||
|
||||
psort_decl * pdecl_manager::mk_psort_builtin_decl(symbol const & n, family_id fid, decl_kind k) {
|
||||
return new (a().allocate(sizeof(psort_builtin_decl))) psort_builtin_decl(m_id_gen.mk(), *this, n, fid, k);
|
||||
|
|
|
@ -62,7 +62,7 @@ class psort_inst_cache;
|
|||
*/
|
||||
class psort : public pdecl {
|
||||
protected:
|
||||
psort_inst_cache * m_inst_cache;
|
||||
psort_inst_cache* m_inst_cache;
|
||||
friend class pdecl_manager;
|
||||
psort(unsigned id, unsigned num_params):pdecl(id, num_params), m_inst_cache(nullptr) {}
|
||||
bool is_psort() const override { return true; }
|
||||
|
@ -86,7 +86,7 @@ typedef ptr_hashtable<psort, psort_hash_proc, psort_eq_proc> psort_table;
|
|||
|
||||
#define PSORT_DECL_VAR_PARAMS UINT_MAX
|
||||
|
||||
typedef enum { PSORT_BASE = 0, PSORT_USER, PSORT_BUILTIN, PSORT_DT } psort_decl_kind;
|
||||
typedef enum { PSORT_BASE = 0, PSORT_USER, PSORT_BUILTIN, PSORT_DT, PSORT_TV } psort_decl_kind;
|
||||
|
||||
class psort_decl : public pdecl {
|
||||
protected:
|
||||
|
@ -123,7 +123,19 @@ public:
|
|||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
||||
std::ostream& display(std::ostream & out) const override;
|
||||
};
|
||||
|
||||
|
||||
class psort_type_var_decl : public psort_decl {
|
||||
protected:
|
||||
friend class pdecl_manager;
|
||||
psort * m_def;
|
||||
psort_type_var_decl(unsigned id, pdecl_manager & m, symbol const & n);
|
||||
size_t obj_size() const override { return sizeof(psort_type_var_decl); }
|
||||
void finalize(pdecl_manager & m) override;
|
||||
public:
|
||||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
||||
std::ostream& display(std::ostream & out) const override;
|
||||
};
|
||||
|
||||
class psort_builtin_decl : public psort_decl {
|
||||
protected:
|
||||
friend class pdecl_manager;
|
||||
|
@ -304,6 +316,7 @@ public:
|
|||
psort_decl * mk_psort_dt_decl(unsigned num_params, symbol const & n);
|
||||
psort_decl * mk_psort_user_decl(unsigned num_params, symbol const & n, psort * def);
|
||||
psort_decl * mk_psort_builtin_decl(symbol const & n, family_id fid, decl_kind k);
|
||||
psort_decl * mk_psort_type_var_decl(symbol const& n);
|
||||
paccessor_decl * mk_paccessor_decl(unsigned num_params, symbol const & s, ptype const & p);
|
||||
pconstructor_decl * mk_pconstructor_decl(unsigned num_params, symbol const & s, symbol const & r, unsigned num, paccessor_decl * const * as);
|
||||
pdatatype_decl * mk_pdatatype_decl(unsigned num_params, symbol const & s, unsigned num, pconstructor_decl * const * cs);
|
||||
|
|
4
src/math/lp/.clang-format
Normal file
4
src/math/lp/.clang-format
Normal file
|
@ -0,0 +1,4 @@
|
|||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 0
|
||||
NamespaceIndentation: All
|
|
@ -19,6 +19,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "util/vector.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
#include "util/vector.h"
|
||||
|
|
|
@ -18,6 +18,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include <string>
|
||||
#include "math/lp/static_matrix.h"
|
||||
namespace lp {
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include "math/lp/numeric_pair.h"
|
||||
#include "math/lp/core_solver_pretty_printer_def.h"
|
||||
template lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::core_solver_pretty_printer(const lp::lp_core_solver_base<lp::mpq, lp::mpq> &, std::ostream & out);
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
|
@ -279,9 +280,9 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print()
|
|||
print_row(i);
|
||||
}
|
||||
m_out << std::endl;
|
||||
if (m_core_solver.inf_set().size()) {
|
||||
if (m_core_solver.inf_heap().size()) {
|
||||
m_out << "inf columns: ";
|
||||
print_vector(m_core_solver.inf_set(), m_out);
|
||||
print_vector(m_core_solver.inf_heap(), m_out);
|
||||
m_out << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include "math/lp/nex.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include "math/lp/lp_settings.h"
|
||||
#include "math/lp/dense_matrix_def.h"
|
||||
#ifdef Z3DEBUG
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#ifdef Z3DEBUG
|
||||
#include "util/vector.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "math/lp/lp_settings.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
replaced rooted_mons.h and rooted_mon, rooted_mon_tabled
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#include "math/lp/emonics.h"
|
||||
#include "math/lp/nla_defs.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
to replace rooted_mons.h and rooted_mon, rooted_mon_tabled
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
#include "math/lp/lp_utils.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/lp_utils.h"
|
||||
#include "util/map.h"
|
||||
|
@ -48,6 +49,15 @@ public:
|
|||
SASSERT(m_vector.empty());
|
||||
m_set.insert(j);
|
||||
}
|
||||
|
||||
void remove(constraint_index j) {
|
||||
m_set.remove(j);
|
||||
unsigned i = 0;
|
||||
for (auto& p : m_vector)
|
||||
if (p.first != j)
|
||||
m_vector[i++] = p;
|
||||
m_vector.shrink(i);
|
||||
}
|
||||
|
||||
void add_expl(const explanation& e) {
|
||||
if (e.m_vector.empty()) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "util/rational.h"
|
||||
#include "math/lp/monic.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include "math/lp/factorization_factory_imp.h"
|
||||
#include "math/lp/nla_core.h"
|
||||
namespace nla {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/factorization.h"
|
||||
namespace nla {
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include <functional>
|
||||
namespace lp {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include "math/lp/gomory.h"
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
|
|
|
@ -15,6 +15,7 @@ Author:
|
|||
|
||||
Revision History:
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/lar_term.h"
|
||||
#include "math/lp/lia_move.h"
|
||||
|
|
|
@ -26,6 +26,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/numeric_pair.h"
|
||||
#include "util/ext_gcd.h"
|
||||
|
|
|
@ -9,6 +9,7 @@ Author:
|
|||
Lev Nachmanson (levnach)
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
#include "math/lp/hnf_cutter.h"
|
||||
|
|
|
@ -14,6 +14,7 @@ Author:
|
|||
Lev Nachmanson (levnach)
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
#include "math/lp/lar_term.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#include "math/lp/horner.h"
|
||||
#include "math/lp/nla_core.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "math/lp/nla_common.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/lp_settings.h"
|
||||
#include "math/lp/lar_constraints.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
#include "util/vector.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
namespace lp {
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include "util/vector.h"
|
||||
#include "math/lp/indexed_vector_def.h"
|
||||
namespace lp {
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
#include "util/vector.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "util/vector.h"
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
Revision History:
|
||||
--*/
|
||||
|
||||
// clang-format off
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
#include "math/lp/int_branch.h"
|
||||
|
@ -63,7 +63,7 @@ int int_branch::find_inf_int_base_column() {
|
|||
mpq small_value(1024);
|
||||
unsigned n = 0;
|
||||
lar_core_solver & lcs = lra.m_mpq_lar_core_solver;
|
||||
unsigned prev_usage = 0; // to quiet down the compile
|
||||
unsigned prev_usage = 0; // to quiet down the compiler
|
||||
unsigned k = 0;
|
||||
unsigned usage;
|
||||
unsigned j;
|
||||
|
|
|
@ -15,6 +15,7 @@ Author:
|
|||
|
||||
Revision History:
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "math/lp/lar_solver.h"
|
||||
|
|
|
@ -15,6 +15,7 @@ Author:
|
|||
|
||||
Revision History:
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
|
|
|
@ -19,6 +19,7 @@ Author:
|
|||
|
||||
Revision History:
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "math/lp/lia_move.h"
|
||||
|
|
|
@ -45,6 +45,7 @@ Accumulative:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
|
|
|
@ -24,6 +24,7 @@ Author:
|
|||
|
||||
Revision History:
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include "math/lp/lia_move.h"
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
// clang-format off
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
#include "math/lp/lp_utils.h"
|
||||
|
@ -14,56 +13,204 @@
|
|||
|
||||
namespace lp {
|
||||
|
||||
int_solver::patcher::patcher(int_solver& lia):
|
||||
lia(lia),
|
||||
lra(lia.lra),
|
||||
lrac(lia.lrac),
|
||||
m_num_nbasic_patches(0),
|
||||
m_patch_cost(0),
|
||||
m_next_patch(0),
|
||||
m_delay(0)
|
||||
{}
|
||||
int_solver::patcher::patcher(int_solver& lia):
|
||||
lia(lia),
|
||||
lra(lia.lra),
|
||||
lrac(lia.lrac)
|
||||
{}
|
||||
|
||||
void int_solver::patcher::remove_fixed_vars_from_base() {
|
||||
unsigned num = lra.A_r().column_count();
|
||||
for (unsigned v = 0; v < num; v++) {
|
||||
if (!lia.is_base(v) || !lia.is_fixed(v))
|
||||
continue;
|
||||
auto const & r = lra.basic2row(v);
|
||||
for (auto const& c : r) {
|
||||
if (c.var() != v && !lia.is_fixed(c.var())) {
|
||||
lra.pivot(c.var(), v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int_solver::patcher::count_non_int() {
|
||||
unsigned non_int = 0;
|
||||
for (auto j : lra.r_basis())
|
||||
if (lra.column_is_int(j) && !lra.column_value_is_int(j))
|
||||
++non_int;
|
||||
return non_int;
|
||||
}
|
||||
|
||||
lia_move int_solver::patcher::patch_basic_columns() {
|
||||
remove_fixed_vars_from_base();
|
||||
lia.settings().stats().m_patches++;
|
||||
lp_assert(lia.is_feasible());
|
||||
|
||||
// unsigned non_int_before, non_int_after;
|
||||
|
||||
// non_int_before = count_non_int();
|
||||
|
||||
|
||||
// unsigned num = lra.A_r().column_count();
|
||||
for (unsigned j : lra.r_basis())
|
||||
if (!lra.get_value(j).is_int())
|
||||
patch_basic_column(j);
|
||||
// non_int_after = count_non_int();
|
||||
// verbose_stream() << non_int_before << " -> " << non_int_after << "\n";
|
||||
|
||||
if (!lia.has_inf_int()) {
|
||||
lia.settings().stats().m_patches_success++;
|
||||
return lia_move::sat;
|
||||
}
|
||||
return lia_move::undef;
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
/**
|
||||
* \brief find integral and minimal, in the absolute values, deltas such that x - alpha*delta is integral too.
|
||||
*/
|
||||
bool get_patching_deltas(const rational& x, const rational& alpha,
|
||||
rational& delta_plus, rational& delta_minus) {
|
||||
auto a1 = numerator(alpha);
|
||||
auto a2 = denominator(alpha);
|
||||
auto x1 = numerator(x);
|
||||
auto x2 = denominator(x);
|
||||
if (!divides(x2, a2))
|
||||
return false;
|
||||
|
||||
// delta has to be integral.
|
||||
// We need to find delta such that x1/x2 + (a1/a2)*delta is integral (we are going to flip the delta sign later).
|
||||
// Then a2*x1/x2 + a1*delta is integral, but x2 and x1 are coprime:
|
||||
// that means that t = a2/x2 is
|
||||
// integral. We established that a2 = x2*t Then x1 + a1*delta*(x2/a2) = x1
|
||||
// + a1*(delta/t) is integral. Taking into account that t and a1 are
|
||||
// coprime we have delta = t*k, where k is an integer.
|
||||
rational t = a2 / x2;
|
||||
// std::cout << "t = " << t << std::endl;
|
||||
// Now we have x1/x2 + (a1/x2)*k is integral, or (x1 + a1*k)/x2 is integral.
|
||||
// It is equivalent to x1 + a1*k = x2*m, where m is an integer
|
||||
// We know that a2 and a1 are coprime, and x2 divides a2, so x2 and a1 are
|
||||
// coprime. We can find u and v such that u*a1 + v*x2 = 1.
|
||||
rational u, v;
|
||||
gcd(a1, x2, u, v);
|
||||
lp_assert(gcd(a1, x2, u, v).is_one());
|
||||
// std::cout << "u = " << u << ", v = " << v << std::endl;
|
||||
// std::cout << "x= " << (x1 / x2) << std::endl;
|
||||
// std::cout << "x + (a1 / a2) * (-u * t) * x1 = "
|
||||
// << x + (a1 / a2) * (-u * t) * x1 << std::endl;
|
||||
lp_assert((x + (a1 / a2) * (-u * t) * x1).is_int());
|
||||
// 1 = (u- l*x2 ) * a1 + (v + l*a1)*x2, for every integer l.
|
||||
rational d = u * t * x1;
|
||||
// We can prove that x+alpha*d is integral,
|
||||
// and any other delta, satisfying x+alpha*delta, is equal to d modulo a2.
|
||||
delta_plus = mod(d, a2);
|
||||
lp_assert(delta_plus > 0);
|
||||
delta_minus = delta_plus - a2;
|
||||
lp_assert(delta_minus < 0);
|
||||
|
||||
bool int_solver::patcher::should_apply() {
|
||||
#if 1
|
||||
return true;
|
||||
#else
|
||||
if (m_delay == 0) {
|
||||
return true;
|
||||
}
|
||||
--m_delay;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* \brief try to patch the basic column v
|
||||
*/
|
||||
bool int_solver::patcher::patch_basic_column_on_row_cell(unsigned v, row_cell<mpq> const& c) {
|
||||
if (v == c.var())
|
||||
return false;
|
||||
if (!lra.column_is_int(c.var())) // could use real to patch integer
|
||||
return false;
|
||||
if (c.coeff().is_int())
|
||||
return false;
|
||||
mpq a = fractional_part(c.coeff());
|
||||
mpq r = fractional_part(lra.get_value(v));
|
||||
lp_assert(0 < r && r < 1);
|
||||
lp_assert(0 < a && a < 1);
|
||||
mpq delta_plus, delta_minus;
|
||||
if (!get_patching_deltas(r, a, delta_plus, delta_minus))
|
||||
return false;
|
||||
|
||||
lia_move int_solver::patcher::operator()() {
|
||||
return patch_nbasic_columns();
|
||||
}
|
||||
if (lia.random() % 2) {
|
||||
return try_patch_column(v, c.var(), delta_plus) ||
|
||||
try_patch_column(v, c.var(), delta_minus);
|
||||
} else {
|
||||
return try_patch_column(v, c.var(), delta_minus) ||
|
||||
try_patch_column(v, c.var(), delta_plus);
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
|
||||
bool int_solver::patcher::try_patch_column(unsigned v, unsigned j, mpq const& delta) {
|
||||
const auto & A = lra.A_r();
|
||||
if (delta < 0) {
|
||||
if (lia.has_lower(j) && lia.get_value(j) + impq(delta) < lra.get_lower_bound(j))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (lia.has_upper(j) && lia.get_value(j) + impq(delta) > lra.get_upper_bound(j))
|
||||
return false;
|
||||
}
|
||||
for (auto const& c : A.column(j)) {
|
||||
unsigned row_index = c.var();
|
||||
unsigned i = lrac.m_r_basis[row_index];
|
||||
auto old_val = lia.get_value(i);
|
||||
auto new_val = old_val - impq(c.coeff()*delta);
|
||||
if (lia.has_lower(i) && new_val < lra.get_lower_bound(i))
|
||||
return false;
|
||||
if (lia.has_upper(i) && new_val > lra.get_upper_bound(i))
|
||||
return false;
|
||||
if (old_val.is_int() && !new_val.is_int()){
|
||||
return false; // do not waste resources on this case
|
||||
}
|
||||
lp_assert(i != v || new_val.is_int())
|
||||
}
|
||||
|
||||
lra.set_value_for_nbasic_column(j, lia.get_value(j) + impq(delta));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void int_solver::patcher::patch_basic_column(unsigned v) {
|
||||
SASSERT(!lia.is_fixed(v));
|
||||
for (auto const& c : lra.basic2row(v))
|
||||
if (patch_basic_column_on_row_cell(v, c))
|
||||
return;
|
||||
}
|
||||
|
||||
lia_move int_solver::patcher::patch_nbasic_columns() {
|
||||
lia.settings().stats().m_patches++;
|
||||
lp_assert(lia.is_feasible());
|
||||
m_num_nbasic_patches = 0;
|
||||
m_patch_cost = 0;
|
||||
for (unsigned j : lia.lrac.m_r_nbasis) {
|
||||
patch_nbasic_column(j);
|
||||
lia_move int_solver::patcher::patch_nbasic_columns() {
|
||||
remove_fixed_vars_from_base();
|
||||
lia.settings().stats().m_patches++;
|
||||
lp_assert(lia.is_feasible());
|
||||
m_patch_success = 0;
|
||||
m_patch_fail = 0;
|
||||
m_num_ones = 0;
|
||||
m_num_divides = 0;
|
||||
//unsigned non_int_before = count_non_int();
|
||||
|
||||
unsigned num = lra.A_r().column_count();
|
||||
for (unsigned v = 0; v < num; v++) {
|
||||
if (lia.is_base(v))
|
||||
continue;
|
||||
patch_nbasic_column(v);
|
||||
}
|
||||
unsigned num_fixed = 0;
|
||||
for (unsigned v = 0; v < num; v++)
|
||||
if (lia.is_fixed(v))
|
||||
++num_fixed;
|
||||
|
||||
lp_assert(lia.is_feasible());
|
||||
//verbose_stream() << "patch " << m_patch_success << " fails " << m_patch_fail << " ones " << m_num_ones << " divides " << m_num_divides << " num fixed " << num_fixed << "\n";
|
||||
//lra.display(verbose_stream());
|
||||
//exit(0);
|
||||
//unsigned non_int_after = count_non_int();
|
||||
|
||||
// verbose_stream() << non_int_before << " -> " << non_int_after << "\n";
|
||||
if (!lia.has_inf_int()) {
|
||||
lia.settings().stats().m_patches_success++;
|
||||
return lia_move::sat;
|
||||
}
|
||||
return lia_move::undef;
|
||||
}
|
||||
lp_assert(lia.is_feasible());
|
||||
if (!lia.has_inf_int()) {
|
||||
lia.settings().stats().m_patches_success++;
|
||||
m_delay = 0;
|
||||
m_next_patch = 0;
|
||||
return lia_move::sat;
|
||||
}
|
||||
if (m_patch_cost > 0 && m_num_nbasic_patches * 10 < m_patch_cost) {
|
||||
m_delay = std::min(20u, m_next_patch++);
|
||||
}
|
||||
else {
|
||||
m_delay = 0;
|
||||
m_next_patch = 0;
|
||||
}
|
||||
return lia_move::undef;
|
||||
}
|
||||
|
||||
void int_solver::patcher::patch_nbasic_column(unsigned j) {
|
||||
impq & val = lrac.m_r_x[j];
|
||||
|
@ -71,17 +218,48 @@ void int_solver::patcher::patch_nbasic_column(unsigned j) {
|
|||
impq l, u;
|
||||
mpq m;
|
||||
bool has_free = lia.get_freedom_interval_for_column(j, inf_l, l, inf_u, u, m);
|
||||
m_patch_cost += lra.A_r().number_of_non_zeroes_in_column(j);
|
||||
if (!has_free) {
|
||||
if (!has_free)
|
||||
return;
|
||||
}
|
||||
bool m_is_one = m.is_one();
|
||||
bool val_is_int = lia.value_is_int(j);
|
||||
|
||||
#if 0
|
||||
const auto & A = lra.A_r();
|
||||
#endif
|
||||
// check whether value of j is already a multiple of m.
|
||||
if (val_is_int && (m_is_one || (val.x / m).is_int())) {
|
||||
if (m_is_one)
|
||||
++m_num_ones;
|
||||
else
|
||||
++m_num_divides;
|
||||
#if 0
|
||||
for (auto c : A.column(j)) {
|
||||
unsigned row_index = c.var();
|
||||
unsigned i = lrac.m_r_basis[row_index];
|
||||
if (!lia.get_value(i).is_int() ||
|
||||
(lia.has_lower(i) && lia.get_value(i) < lra.get_lower_bound(i)) ||
|
||||
(lia.has_upper(i) && lia.get_value(i) > lra.get_upper_bound(i))) {
|
||||
verbose_stream() << "skip " << j << " " << m << ": ";
|
||||
lia.display_row(verbose_stream(), A.m_rows[row_index]);
|
||||
verbose_stream() << "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!m_is_one) {
|
||||
// lia.display_column(verbose_stream(), j);
|
||||
for (auto c : A.column(j)) {
|
||||
continue;
|
||||
unsigned row_index = c.var();
|
||||
lia.display_row(verbose_stream(), A.m_rows[row_index]);
|
||||
verbose_stream() << "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE("patch_int",
|
||||
tout << "TARGET j" << j << " -> [";
|
||||
if (inf_l) tout << "-oo"; else tout << l;
|
||||
|
@ -89,9 +267,33 @@ void int_solver::patcher::patch_nbasic_column(unsigned j) {
|
|||
if (inf_u) tout << "oo"; else tout << u;
|
||||
tout << "]";
|
||||
tout << ", m: " << m << ", val: " << val << ", is_int: " << lra.column_is_int(j) << "\n";);
|
||||
|
||||
#if 0
|
||||
verbose_stream() << "path " << m << " ";
|
||||
if (!inf_l) verbose_stream() << "infl " << l.x << " ";
|
||||
if (!inf_u) verbose_stream() << "infu " << u.x << " ";
|
||||
verbose_stream() << "\n";
|
||||
if (m.is_big() || (!inf_l && l.x.is_big()) || (!inf_u && u.x.is_big())) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
verbose_stream() << "TARGET v" << j << " -> [";
|
||||
if (inf_l) verbose_stream() << "-oo"; else verbose_stream() << ceil(l.x) << " " << l << "\n";
|
||||
verbose_stream() << ", ";
|
||||
if (inf_u) verbose_stream() << "oo"; else verbose_stream() << floor(u.x) << " " << u << "\n";
|
||||
verbose_stream() << "]";
|
||||
verbose_stream() << ", m: " << m << ", val: " << val << ", is_int: " << lra.column_is_int(j) << "\n";
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (!inf_l)
|
||||
l = impq(ceil(l));
|
||||
if (!inf_u)
|
||||
u = impq(floor(u));
|
||||
#endif
|
||||
|
||||
if (!inf_l) {
|
||||
l = impq(m_is_one ? ceil(l) : m * ceil(l / m));
|
||||
if (inf_u || l <= u) {
|
||||
|
@ -99,8 +301,23 @@ void int_solver::patcher::patch_nbasic_column(unsigned j) {
|
|||
lra.set_value_for_nbasic_column(j, l);
|
||||
}
|
||||
else {
|
||||
--m_num_nbasic_patches;
|
||||
//verbose_stream() << "fail: " << j << " " << m << "\n";
|
||||
++m_patch_fail;
|
||||
TRACE("patch_int", tout << "not patching " << l << "\n";);
|
||||
#if 0
|
||||
verbose_stream() << "not patched\n";
|
||||
for (auto c : A.column(j)) {
|
||||
unsigned row_index = c.var();
|
||||
unsigned i = lrac.m_r_basis[row_index];
|
||||
if (!lia.get_value(i).is_int() ||
|
||||
(lia.has_lower(i) && lia.get_value(i) < lra.get_lower_bound(i)) ||
|
||||
(lia.has_upper(i) && lia.get_value(i) > lra.get_upper_bound(i))) {
|
||||
lia.display_row(verbose_stream(), A.m_rows[row_index]);
|
||||
verbose_stream() << "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!inf_u) {
|
||||
|
@ -112,7 +329,21 @@ void int_solver::patcher::patch_nbasic_column(unsigned j) {
|
|||
lra.set_value_for_nbasic_column(j, impq(0));
|
||||
TRACE("patch_int", tout << "patching with 0\n";);
|
||||
}
|
||||
++m_num_nbasic_patches;
|
||||
++m_patch_success;
|
||||
#if 0
|
||||
verbose_stream() << "patched " << j << "\n";
|
||||
for (auto c : A.column(j)) {
|
||||
unsigned row_index = c.var();
|
||||
unsigned i = lrac.m_r_basis[row_index];
|
||||
if (!lia.get_value(i).is_int() ||
|
||||
(lia.has_lower(i) && lia.get_value(i) < lra.get_lower_bound(i)) ||
|
||||
(lia.has_upper(i) && lia.get_value(i) > lra.get_upper_bound(i))) {
|
||||
lia.display_row(verbose_stream(), A.m_rows[row_index]);
|
||||
verbose_stream() << "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int_solver::int_solver(lar_solver& lar_slv) :
|
||||
|
@ -326,7 +557,7 @@ static void set_upper(impq & u, bool & inf_u, impq const & v) {
|
|||
|
||||
// this function assumes that all basic columns dependend on j are feasible
|
||||
bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m) {
|
||||
if (lrac.m_r_heading[j] >= 0) // the basic var
|
||||
if (lrac.m_r_heading[j] >= 0 || is_fixed(j)) // basic or fixed var
|
||||
return false;
|
||||
|
||||
TRACE("random_update", display_column(tout, j) << ", is_int = " << column_is_int(j) << "\n";);
|
||||
|
@ -361,10 +592,9 @@ bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq
|
|||
unsigned i = lrac.m_r_basis[row_index];
|
||||
impq const & xi = get_value(i);
|
||||
lp_assert(lrac.m_r_solver.column_is_feasible(i));
|
||||
if (column_is_int(i) && !a.is_int())
|
||||
if (column_is_int(i) && !a.is_int() && xi.is_int())
|
||||
m = lcm(m, denominator(a));
|
||||
|
||||
|
||||
|
||||
if (!inf_l && !inf_u) {
|
||||
if (l == u)
|
||||
continue;
|
||||
|
@ -372,15 +602,15 @@ bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq
|
|||
|
||||
if (a.is_neg()) {
|
||||
if (has_lower(i))
|
||||
set_lower(l, inf_l, delta(a, xi, lrac.m_r_lower_bounds()[i]));
|
||||
set_lower(l, inf_l, delta(a, xi, lra.get_lower_bound(i)));
|
||||
if (has_upper(i))
|
||||
set_upper(u, inf_u, delta(a, xi, lrac.m_r_upper_bounds()[i]));
|
||||
set_upper(u, inf_u, delta(a, xi, lra.get_upper_bound(i)));
|
||||
}
|
||||
else {
|
||||
if (has_upper(i))
|
||||
set_lower(l, inf_l, delta(a, xi, lrac.m_r_upper_bounds()[i]));
|
||||
set_lower(l, inf_l, delta(a, xi, lra.get_upper_bound(i)));
|
||||
if (has_lower(i))
|
||||
set_upper(u, inf_u, delta(a, xi, lrac.m_r_lower_bounds()[i]));
|
||||
set_upper(u, inf_u, delta(a, xi, lra.get_lower_bound(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,14 +709,11 @@ bool int_solver::at_upper(unsigned j) const {
|
|||
}
|
||||
|
||||
std::ostream & int_solver::display_row(std::ostream & out, lp::row_strip<rational> const & row) const {
|
||||
bool first = true;
|
||||
bool first = true;
|
||||
auto & rslv = lrac.m_r_solver;
|
||||
for (const auto &c : row)
|
||||
{
|
||||
if (is_fixed(c.var()))
|
||||
{
|
||||
if (!get_value(c.var()).is_zero())
|
||||
{
|
||||
for (const auto &c : row) {
|
||||
if (is_fixed(c.var())) {
|
||||
if (!get_value(c.var()).is_zero()) {
|
||||
impq val = get_value(c.var()) * c.coeff();
|
||||
if (!first && val.is_pos())
|
||||
out << "+";
|
||||
|
@ -505,17 +732,11 @@ for (const auto &c : row)
|
|||
}
|
||||
else if (c.coeff().is_minus_one())
|
||||
out << "-";
|
||||
else
|
||||
{
|
||||
if (c.coeff().is_pos())
|
||||
{
|
||||
if (!first)
|
||||
out << "+";
|
||||
}
|
||||
else {
|
||||
if (c.coeff().is_pos() && !first)
|
||||
out << "+";
|
||||
if (c.coeff().is_big())
|
||||
{
|
||||
out << " b*";
|
||||
}
|
||||
else
|
||||
out << c.coeff();
|
||||
}
|
||||
|
@ -523,8 +744,7 @@ for (const auto &c : row)
|
|||
first = false;
|
||||
}
|
||||
out << "\n";
|
||||
for (const auto &c : row)
|
||||
{
|
||||
for (const auto &c : row) {
|
||||
if (is_fixed(c.var()))
|
||||
continue;
|
||||
rslv.print_column_info(c.var(), out);
|
||||
|
@ -533,14 +753,13 @@ for (const auto &c : row)
|
|||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& int_solver::display_row_info(std::ostream & out, unsigned row_index) const {
|
||||
auto & rslv = lrac.m_r_solver;
|
||||
auto const& row = rslv.m_A.m_rows[row_index];
|
||||
return display_row(out, row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool int_solver::shift_var(unsigned j, unsigned range) {
|
||||
if (is_fixed(j) || is_base(j))
|
||||
return false;
|
||||
|
@ -549,11 +768,13 @@ bool int_solver::shift_var(unsigned j, unsigned range) {
|
|||
bool inf_l = false, inf_u = false;
|
||||
impq l, u;
|
||||
mpq m;
|
||||
VERIFY(get_freedom_interval_for_column(j, inf_l, l, inf_u, u, m) || settings().get_cancel_flag());
|
||||
if (!get_freedom_interval_for_column(j, inf_l, l, inf_u, u, m))
|
||||
return false;
|
||||
if (settings().get_cancel_flag())
|
||||
return false;
|
||||
const impq & x = get_value(j);
|
||||
// x, the value of j column, might be shifted on a multiple of m
|
||||
|
||||
if (inf_l && inf_u) {
|
||||
impq new_val = m * impq(random() % (range + 1)) + x;
|
||||
lra.set_value_for_nbasic_column(j, new_val);
|
||||
|
@ -570,6 +791,7 @@ bool int_solver::shift_var(unsigned j, unsigned range) {
|
|||
if (!inf_l && !inf_u && l >= u)
|
||||
return false;
|
||||
|
||||
|
||||
if (inf_u) {
|
||||
SASSERT(!inf_l);
|
||||
impq new_val = x + m * impq(random() % (range + 1));
|
||||
|
@ -640,21 +862,14 @@ int int_solver::select_int_infeasible_var() {
|
|||
unsigned n = 0;
|
||||
lar_core_solver & lcs = lra.m_mpq_lar_core_solver;
|
||||
unsigned prev_usage = 0; // to quiet down the compile
|
||||
unsigned k = 0;
|
||||
unsigned usage;
|
||||
unsigned j;
|
||||
|
||||
enum state { small_box, is_small_value, any_value, not_found };
|
||||
state st = not_found;
|
||||
|
||||
// 1. small box
|
||||
// 2. small value
|
||||
// 3. any value
|
||||
for (; k < lra.r_basis().size(); k++) {
|
||||
j = lra.r_basis()[k];
|
||||
for (unsigned j : lra.r_basis()) {
|
||||
if (!column_is_int_inf(j))
|
||||
continue;
|
||||
usage = lra.usage_in_terms(j);
|
||||
unsigned usage = lra.usage_in_terms(j);
|
||||
if (is_boxed(j) && (new_range = lcs.m_r_upper_bounds()[j].x - lcs.m_r_lower_bounds()[j].x - rational(2*usage)) <= small_value) {
|
||||
SASSERT(!is_fixed(j));
|
||||
if (st != small_box) {
|
||||
|
@ -688,12 +903,12 @@ int int_solver::select_int_infeasible_var() {
|
|||
continue;
|
||||
SASSERT(st == not_found || st == any_value);
|
||||
st = any_value;
|
||||
if (n == 0 /*|| usage > prev_usage*/) {
|
||||
if (n == 0 || usage > prev_usage) {
|
||||
result = j;
|
||||
prev_usage = usage;
|
||||
n = 1;
|
||||
}
|
||||
else if (usage > 0 && /*usage == prev_usage && */ (random() % (++n) == 0))
|
||||
else if (usage > 0 && usage == prev_usage && (random() % (++n) == 0))
|
||||
result = j;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/lp_settings.h"
|
||||
#include "math/lp/static_matrix.h"
|
||||
|
@ -44,17 +45,23 @@ class int_solver {
|
|||
int_solver& lia;
|
||||
lar_solver& lra;
|
||||
lar_core_solver& lrac;
|
||||
unsigned m_num_nbasic_patches;
|
||||
unsigned m_patch_cost;
|
||||
unsigned m_next_patch;
|
||||
unsigned m_delay;
|
||||
unsigned m_patch_success = 0;
|
||||
unsigned m_patch_fail = 0;
|
||||
unsigned m_num_ones = 0;
|
||||
unsigned m_num_divides = 0;
|
||||
public:
|
||||
patcher(int_solver& lia);
|
||||
bool should_apply();
|
||||
lia_move operator()();
|
||||
bool should_apply() const { return true; }
|
||||
lia_move operator()() { return patch_basic_columns(); }
|
||||
void patch_nbasic_column(unsigned j);
|
||||
bool patch_basic_column_on_row_cell(unsigned v, row_cell<mpq> const& c);
|
||||
void patch_basic_column(unsigned j);
|
||||
bool try_patch_column(unsigned v, unsigned j, mpq const& delta);
|
||||
unsigned count_non_int();
|
||||
private:
|
||||
void remove_fixed_vars_from_base();
|
||||
lia_move patch_nbasic_columns();
|
||||
lia_move patch_basic_columns();
|
||||
};
|
||||
|
||||
lar_solver& lra;
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
#include <utility>
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
|
@ -5,6 +5,7 @@ Author:
|
|||
Lev Nachmanson (levnach)
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "util/vector.h"
|
||||
#include <string>
|
||||
|
@ -16,7 +17,7 @@ Author:
|
|||
#include "math/lp/stacked_vector.h"
|
||||
#include "util/stacked_value.h"
|
||||
namespace lp {
|
||||
|
||||
// clang-format off
|
||||
class lar_core_solver {
|
||||
vector<std::pair<mpq, unsigned>> m_infeasible_linear_combination;
|
||||
int m_infeasible_sum_sign; // todo: get rid of this field
|
||||
|
@ -93,6 +94,8 @@ public:
|
|||
|
||||
void solve();
|
||||
|
||||
void pivot(int entering, int leaving) { m_r_solver.pivot(entering, leaving); }
|
||||
|
||||
bool lower_bounds_are_set() const { return true; }
|
||||
|
||||
const indexed_vector<mpq> & get_pivot_row() const {
|
||||
|
|
|
@ -9,6 +9,7 @@ Revision History:
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
@ -85,8 +86,8 @@ unsigned lar_core_solver::get_number_of_non_ints() const {
|
|||
void lar_core_solver::solve() {
|
||||
TRACE("lar_solver", tout << m_r_solver.get_status() << "\n";);
|
||||
lp_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lp_assert(m_r_solver.inf_set_is_correct());
|
||||
TRACE("find_feas_stats", tout << "infeasibles = " << m_r_solver.inf_set_size() << ", int_infs = " << get_number_of_non_ints() << std::endl;);
|
||||
lp_assert(m_r_solver.inf_heap_is_correct());
|
||||
TRACE("find_feas_stats", tout << "infeasibles = " << m_r_solver.inf_heap_size() << ", int_infs = " << get_number_of_non_ints() << std::endl;);
|
||||
if (m_r_solver.current_x_is_feasible() && m_r_solver.m_look_for_feasible_solution_only) {
|
||||
m_r_solver.set_status(lp_status::OPTIMAL);
|
||||
TRACE("lar_solver", tout << m_r_solver.get_status() << "\n";);
|
||||
|
@ -117,11 +118,9 @@ void lar_core_solver::solve() {
|
|||
}
|
||||
lp_assert(r_basis_is_OK());
|
||||
lp_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lp_assert(m_r_solver.inf_set_is_correct());
|
||||
|
||||
TRACE("lar_solver", tout << m_r_solver.get_status() << "\n";);
|
||||
}
|
||||
|
||||
lp_assert(m_r_solver.inf_heap_is_correct());
|
||||
|
||||
TRACE("lar_solver", tout << m_r_solver.get_status() << "\n";);
|
||||
}
|
||||
|
||||
} // namespace lp
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Nikolaj Bjorner, Lev Nachmanson
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
#include "math/lp/lar_solver.h"
|
||||
#include "smt/params/smt_params_helper.hpp"
|
||||
|
||||
|
@ -41,7 +41,6 @@ namespace lp {
|
|||
for (auto t : m_terms)
|
||||
delete t;
|
||||
}
|
||||
|
||||
|
||||
bool lar_solver::sizes_are_correct() const {
|
||||
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size());
|
||||
|
@ -50,7 +49,6 @@ namespace lp {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& lar_solver::print_implied_bound(const implied_bound& be, std::ostream& out) const {
|
||||
out << "implied bound\n";
|
||||
unsigned v = be.m_j;
|
||||
|
@ -215,7 +213,7 @@ namespace lp {
|
|||
|
||||
void lar_solver::fill_explanation_from_crossed_bounds_column(explanation& evidence) const {
|
||||
lp_assert(static_cast<int>(get_column_type(m_crossed_bounds_column)) >= static_cast<int>(column_type::boxed));
|
||||
lp_assert(!m_mpq_lar_core_solver.m_r_solver.column_is_feasible(m_crossed_bounds_column));
|
||||
lp_assert(!column_is_feasible(m_crossed_bounds_column));
|
||||
|
||||
// this is the case when the lower bound is in conflict with the upper one
|
||||
const ul_pair& ul = m_columns_to_ul_pairs[m_crossed_bounds_column];
|
||||
|
@ -244,6 +242,14 @@ namespace lp {
|
|||
set.erase(j);
|
||||
}
|
||||
|
||||
void lar_solver::clean_popped_elements_for_heap(unsigned n, lpvar_heap& heap) {
|
||||
vector<int> to_remove;
|
||||
for (unsigned j : heap)
|
||||
if (j >= n)
|
||||
to_remove.push_back(j);
|
||||
for (unsigned j : to_remove)
|
||||
heap.erase(j);
|
||||
}
|
||||
|
||||
|
||||
void lar_solver::pop(unsigned k) {
|
||||
|
@ -271,7 +277,7 @@ namespace lp {
|
|||
|
||||
unsigned m = A_r().row_count();
|
||||
clean_popped_elements(m, m_rows_with_changed_bounds);
|
||||
clean_inf_set_of_r_solver_after_pop();
|
||||
clean_inf_heap_of_r_solver_after_pop();
|
||||
lp_assert(
|
||||
m_settings.simplex_strategy() == simplex_strategy_enum::undecided ||
|
||||
m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau());
|
||||
|
@ -328,7 +334,7 @@ namespace lp {
|
|||
|
||||
void lar_solver::set_costs_to_zero(const lar_term& term) {
|
||||
auto& rslv = m_mpq_lar_core_solver.m_r_solver;
|
||||
auto& jset = m_mpq_lar_core_solver.m_r_solver.inf_set(); // hijack this set that should be empty right now
|
||||
auto& jset = m_mpq_lar_core_solver.m_r_solver.inf_heap(); // hijack this set that should be empty right now
|
||||
lp_assert(jset.empty());
|
||||
|
||||
for (lar_term::ival p : term) {
|
||||
|
@ -667,16 +673,16 @@ namespace lp {
|
|||
m_mpq_lar_core_solver.m_r_solver.add_delta_to_x_and_track_feasibility(bj, -A_r().get_val(c) * delta);
|
||||
TRACE("change_x_del",
|
||||
tout << "changed basis column " << bj << ", it is " <<
|
||||
(m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj) ? "feas" : "inf") << std::endl;);
|
||||
(column_is_feasible(bj) ? "feas" : "inf") << std::endl;);
|
||||
}
|
||||
}
|
||||
|
||||
void lar_solver::update_x_and_inf_costs_for_column_with_changed_bounds(unsigned j) {
|
||||
if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) {
|
||||
if (costs_are_used()) {
|
||||
bool was_infeas = m_mpq_lar_core_solver.m_r_solver.inf_set_contains(j);
|
||||
bool was_infeas = m_mpq_lar_core_solver.m_r_solver.inf_heap_contains(j);
|
||||
m_mpq_lar_core_solver.m_r_solver.track_column_feasibility(j);
|
||||
if (was_infeas != m_mpq_lar_core_solver.m_r_solver.inf_set_contains(j))
|
||||
if (was_infeas != m_mpq_lar_core_solver.m_r_solver.inf_heap_contains(j))
|
||||
m_basic_columns_with_changed_cost.insert(j);
|
||||
}
|
||||
else {
|
||||
|
@ -1293,12 +1299,12 @@ namespace lp {
|
|||
lp_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct());
|
||||
}
|
||||
|
||||
void lar_solver::clean_inf_set_of_r_solver_after_pop() {
|
||||
void lar_solver::clean_inf_heap_of_r_solver_after_pop() {
|
||||
vector<unsigned> became_feas;
|
||||
clean_popped_elements(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.inf_set());
|
||||
clean_popped_elements_for_heap(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.inf_heap());
|
||||
std::unordered_set<unsigned> basic_columns_with_changed_cost;
|
||||
m_inf_index_copy.reset();
|
||||
for (auto j : m_mpq_lar_core_solver.m_r_solver.inf_set())
|
||||
for (auto j : m_mpq_lar_core_solver.m_r_solver.inf_heap())
|
||||
m_inf_index_copy.push_back(j);
|
||||
for (auto j : m_inf_index_copy) {
|
||||
if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) {
|
||||
|
@ -1316,16 +1322,16 @@ namespace lp {
|
|||
lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0);
|
||||
m_mpq_lar_core_solver.m_r_solver.m_d[j] -= m_mpq_lar_core_solver.m_r_solver.m_costs[j];
|
||||
m_mpq_lar_core_solver.m_r_solver.m_costs[j] = zero_of_type<mpq>();
|
||||
m_mpq_lar_core_solver.m_r_solver.remove_column_from_inf_set(j);
|
||||
m_mpq_lar_core_solver.m_r_solver.remove_column_from_inf_heap(j);
|
||||
}
|
||||
became_feas.clear();
|
||||
for (unsigned j : m_mpq_lar_core_solver.m_r_solver.inf_set()) {
|
||||
for (unsigned j : m_mpq_lar_core_solver.m_r_solver.inf_heap()) {
|
||||
lp_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0);
|
||||
if (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j))
|
||||
if (column_is_feasible(j))
|
||||
became_feas.push_back(j);
|
||||
}
|
||||
for (unsigned j : became_feas)
|
||||
m_mpq_lar_core_solver.m_r_solver.remove_column_from_inf_set(j);
|
||||
m_mpq_lar_core_solver.m_r_solver.remove_column_from_inf_heap(j);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1346,8 +1352,8 @@ namespace lp {
|
|||
}
|
||||
|
||||
bool lar_solver::term_is_int(const vector<std::pair<mpq, unsigned int>>& coeffs) const {
|
||||
for (auto const& p : coeffs)
|
||||
if (!(column_is_int(p.second) && p.first.is_int()))
|
||||
for (auto const& [coeff, v] : coeffs)
|
||||
if (!(column_is_int(v) && coeff.is_int()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1374,66 +1380,6 @@ namespace lp {
|
|||
return m_mpq_lar_core_solver.column_is_free(j);
|
||||
}
|
||||
|
||||
// column is at lower or upper bound, lower and upper bound are different.
|
||||
// the lower/upper bound is not strict.
|
||||
// the LP obtained by making the bound strict is infeasible
|
||||
// -> the column has to be fixed
|
||||
bool lar_solver::is_fixed_at_bound(column_index const& j) {
|
||||
if (column_is_fixed(j))
|
||||
return false;
|
||||
mpq val;
|
||||
if (!has_value(j, val))
|
||||
return false;
|
||||
lp::lconstraint_kind k;
|
||||
if (column_has_upper_bound(j) &&
|
||||
get_upper_bound(j).x == val) {
|
||||
verbose_stream() << "check upper " << j << "\n";
|
||||
push();
|
||||
if (column_is_int(j))
|
||||
k = LE, val -= 1;
|
||||
else
|
||||
k = LT;
|
||||
auto ci = mk_var_bound(j, k, val);
|
||||
update_column_type_and_bound(j, k, val, ci);
|
||||
auto st = find_feasible_solution();
|
||||
pop(1);
|
||||
return st == lp_status::INFEASIBLE;
|
||||
}
|
||||
if (column_has_lower_bound(j) &&
|
||||
get_lower_bound(j).x == val) {
|
||||
verbose_stream() << "check lower " << j << "\n";
|
||||
push();
|
||||
if (column_is_int(j))
|
||||
k = GE, val += 1;
|
||||
else
|
||||
k = GT;
|
||||
auto ci = mk_var_bound(j, k, val);
|
||||
update_column_type_and_bound(j, k, val, ci);
|
||||
auto st = find_feasible_solution();
|
||||
pop(1);
|
||||
return st == lp_status::INFEASIBLE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lar_solver::has_fixed_at_bound() {
|
||||
verbose_stream() << "has-fixed-at-bound\n";
|
||||
unsigned num_fixed = 0;
|
||||
for (unsigned j = 0; j < A_r().m_columns.size(); ++j) {
|
||||
auto ci = column_index(j);
|
||||
if (is_fixed_at_bound(ci)) {
|
||||
++num_fixed;
|
||||
verbose_stream() << "fixed " << j << "\n";
|
||||
}
|
||||
}
|
||||
verbose_stream() << "num fixed " << num_fixed << "\n";
|
||||
if (num_fixed > 0)
|
||||
find_feasible_solution();
|
||||
return num_fixed > 0;
|
||||
}
|
||||
|
||||
|
||||
// below is the initialization functionality of lar_solver
|
||||
|
||||
bool lar_solver::strategy_is_undecided() const {
|
||||
|
@ -1504,7 +1450,7 @@ namespace lp {
|
|||
m_mpq_lar_core_solver.m_r_x.resize(j + 1);
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds.increase_size_by_one();
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds.increase_size_by_one();
|
||||
m_mpq_lar_core_solver.m_r_solver.inf_set_increase_size_by_one();
|
||||
m_mpq_lar_core_solver.m_r_solver.inf_heap_increase_size_by_one();
|
||||
m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1);
|
||||
m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1);
|
||||
lp_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method
|
||||
|
@ -1609,6 +1555,18 @@ namespace lp {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief ensure there is a column index corresponding to vi
|
||||
* If vi is already a column, just return vi
|
||||
* If vi is for a term, then create a row that uses the term.
|
||||
*/
|
||||
var_index lar_solver::ensure_column(var_index vi) {
|
||||
if (lp::tv::is_term(vi))
|
||||
return to_column(vi);
|
||||
else
|
||||
return vi;
|
||||
}
|
||||
|
||||
|
||||
void lar_solver::add_row_from_term_no_constraint(const lar_term* term, unsigned term_ext_index) {
|
||||
TRACE("dump_terms", print_term(*term, tout) << std::endl;);
|
||||
|
@ -1780,13 +1738,20 @@ namespace lp {
|
|||
lconstraint_kind kind,
|
||||
const mpq& right_side,
|
||||
constraint_index constr_index) {
|
||||
TRACE("lar_solver_feas", tout << "j = " << j << " was " << (this->column_is_feasible(j)?"feas":"non-feas") << std::endl;);
|
||||
m_constraints.activate(constr_index);
|
||||
if (column_has_upper_bound(j))
|
||||
update_column_type_and_bound_with_ub(j, kind, right_side, constr_index);
|
||||
else
|
||||
update_column_type_and_bound_with_no_ub(j, kind, right_side, constr_index);
|
||||
TRACE("lar_solver_feas", tout << "j = " << j << " became " << (this->column_is_feasible(j)?"feas":"non-feas") << ", and " << (this->column_is_bounded(j)? "bounded":"non-bounded") << std::endl;);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
void lar_solver::insert_to_columns_with_changed_bounds(unsigned j) {
|
||||
m_columns_with_changed_bounds.insert(j);
|
||||
TRACE("lar_solver", tout << "column " << j << (column_is_feasible(j) ? " feas" : " non-feas") << "\n";);
|
||||
}
|
||||
// clang-format off
|
||||
void lar_solver::update_column_type_and_bound_check_on_equal(unsigned j,
|
||||
lconstraint_kind kind,
|
||||
const mpq& right_side,
|
||||
|
@ -1876,117 +1841,111 @@ namespace lp {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// clang-format on
|
||||
void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) {
|
||||
lp_assert(column_has_lower_bound(j) && column_has_upper_bound(j));
|
||||
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed ||
|
||||
m_mpq_lar_core_solver.m_column_types[j] == column_type::fixed);
|
||||
m_mpq_lar_core_solver.m_column_types[j] == column_type::fixed);
|
||||
|
||||
mpq y_of_bound(0);
|
||||
switch (kind) {
|
||||
case LT:
|
||||
y_of_bound = -1;
|
||||
case LE:
|
||||
{
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
case LT:
|
||||
y_of_bound = -1;
|
||||
case LE: {
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return;
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, ci);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
}
|
||||
if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return;
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, ci);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
break;
|
||||
case GT:
|
||||
y_of_bound = 1;
|
||||
case GE:
|
||||
{
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
case GT:
|
||||
y_of_bound = 1;
|
||||
case GE: {
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
return;
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
}
|
||||
case EQ: {
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j] || v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
set_upper_bound_witness(j, ci);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
break;
|
||||
}
|
||||
if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
return;
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
}
|
||||
break;
|
||||
case EQ:
|
||||
{
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j] || v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
set_upper_bound_witness(j, ci);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (m_mpq_lar_core_solver.m_r_upper_bounds[j] == m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) {
|
||||
lp_assert(column_has_lower_bound(j) && !column_has_upper_bound(j));
|
||||
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::lower_bound);
|
||||
|
||||
mpq y_of_bound(0);
|
||||
switch (kind) {
|
||||
case LT:
|
||||
y_of_bound = -1;
|
||||
case LE:
|
||||
{
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, ci);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
}
|
||||
break;
|
||||
case GT:
|
||||
y_of_bound = 1;
|
||||
case GE:
|
||||
{
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
return;
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
set_lower_bound_witness(j, ci);
|
||||
}
|
||||
break;
|
||||
case EQ:
|
||||
{
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
case LT:
|
||||
y_of_bound = -1;
|
||||
case LE: {
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
}
|
||||
case GT:
|
||||
y_of_bound = 1;
|
||||
case GE: {
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
return;
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, ci);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
}
|
||||
case EQ: {
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
}
|
||||
|
||||
set_upper_bound_witness(j, ci);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
break;
|
||||
}
|
||||
|
||||
set_upper_bound_witness(j, ci);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
void lar_solver::update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) {
|
||||
lp_assert(!column_has_lower_bound(j) && column_has_upper_bound(j));
|
||||
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::upper_bound);
|
||||
|
@ -2012,9 +1971,10 @@ namespace lp {
|
|||
set_infeasible_column(j);
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
|
||||
}
|
||||
break;
|
||||
case EQ:
|
||||
|
@ -2035,48 +1995,44 @@ namespace lp {
|
|||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) {
|
||||
lp_assert(!column_has_lower_bound(j) && !column_has_upper_bound(j));
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
|
||||
mpq y_of_bound(0);
|
||||
switch (kind) {
|
||||
case LT:
|
||||
y_of_bound = -1;
|
||||
case LE:
|
||||
{
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound;
|
||||
}
|
||||
break;
|
||||
case GT:
|
||||
y_of_bound = 1;
|
||||
case GE:
|
||||
{
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::lower_bound;
|
||||
}
|
||||
break;
|
||||
case EQ:
|
||||
{
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
set_upper_bound_witness(j, ci);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
break;
|
||||
}
|
||||
case LT:
|
||||
y_of_bound = -1;
|
||||
case LE: {
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound;
|
||||
} break;
|
||||
case GT:
|
||||
y_of_bound = 1;
|
||||
case GE: {
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::lower_bound;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
} break;
|
||||
case EQ: {
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
set_upper_bound_witness(j, ci);
|
||||
set_lower_bound_witness(j, ci);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
bool lar_solver::column_corresponds_to_term(unsigned j) const {
|
||||
return tv::is_term(m_var_register.local_to_external(j));
|
||||
}
|
||||
|
@ -2180,8 +2136,8 @@ namespace lp {
|
|||
}
|
||||
|
||||
bool lar_solver::get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, constraint_index& ci, bool& upper_bound) const {
|
||||
lp_assert(t.is_term())
|
||||
unsigned j;
|
||||
lp_assert(t.is_term());
|
||||
unsigned j;
|
||||
bool is_int;
|
||||
if (!m_var_register.external_is_used(t.index(), j, is_int))
|
||||
return false; // the term does not have a bound because it does not correspond to a column
|
||||
|
|
|
@ -17,30 +17,32 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "util/vector.h"
|
||||
#include <utility>
|
||||
#include "util/debug.h"
|
||||
#include "util/buffer.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "math/lp/bound_analyzer_on_row.h"
|
||||
#include "math/lp/implied_bound.h"
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_constraints.h"
|
||||
#include "math/lp/lar_core_solver.h"
|
||||
#include "math/lp/numeric_pair.h"
|
||||
#include "math/lp/lp_primal_core_solver.h"
|
||||
#include "math/lp/random_updater.h"
|
||||
#include "util/stacked_value.h"
|
||||
#include "math/lp/stacked_vector.h"
|
||||
#include "math/lp/implied_bound.h"
|
||||
#include "math/lp/bound_analyzer_on_row.h"
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/nra_solver.h"
|
||||
#include "math/lp/lp_types.h"
|
||||
#include "math/lp/lp_bound_propagator.h"
|
||||
#include "math/lp/lp_primal_core_solver.h"
|
||||
#include "math/lp/lp_types.h"
|
||||
#include "math/lp/nra_solver.h"
|
||||
#include "math/lp/numeric_pair.h"
|
||||
#include "math/lp/random_updater.h"
|
||||
#include "math/lp/stacked_vector.h"
|
||||
#include "util/buffer.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/stacked_value.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
namespace lp {
|
||||
|
||||
|
@ -48,10 +50,9 @@ class int_branch;
|
|||
class int_solver;
|
||||
class lar_solver : public column_namer {
|
||||
struct term_hasher {
|
||||
std::size_t operator()(const lar_term &t) const
|
||||
{
|
||||
using std::size_t;
|
||||
std::size_t operator()(const lar_term& t) const {
|
||||
using std::hash;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
size_t seed = 0;
|
||||
int i = 0;
|
||||
|
@ -66,110 +67,106 @@ class lar_solver : public column_namer {
|
|||
};
|
||||
|
||||
struct term_comparer {
|
||||
bool operator()(const lar_term &a, const lar_term& b) const
|
||||
{
|
||||
return a == b;
|
||||
bool operator()(const lar_term& a, const lar_term& b) const {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////// fields //////////////////////////
|
||||
lp_settings m_settings;
|
||||
lp_status m_status = lp_status::UNKNOWN;
|
||||
stacked_value<simplex_strategy_enum> m_simplex_strategy;
|
||||
lp_settings m_settings;
|
||||
lp_status m_status = lp_status::UNKNOWN;
|
||||
stacked_value<simplex_strategy_enum> m_simplex_strategy;
|
||||
// such can be found at the initialization step: u < l
|
||||
stacked_value<int> m_crossed_bounds_column;
|
||||
lar_core_solver m_mpq_lar_core_solver;
|
||||
int_solver * m_int_solver = nullptr;
|
||||
bool m_need_register_terms = false;
|
||||
var_register m_var_register;
|
||||
var_register m_term_register;
|
||||
stacked_vector<ul_pair> m_columns_to_ul_pairs;
|
||||
constraint_set m_constraints;
|
||||
stacked_value<int> m_crossed_bounds_column;
|
||||
lar_core_solver m_mpq_lar_core_solver;
|
||||
int_solver* m_int_solver = nullptr;
|
||||
bool m_need_register_terms = false;
|
||||
var_register m_var_register;
|
||||
var_register m_term_register;
|
||||
stacked_vector<ul_pair> m_columns_to_ul_pairs;
|
||||
constraint_set m_constraints;
|
||||
// the set of column indices j such that bounds have changed for j
|
||||
u_set m_columns_with_changed_bounds;
|
||||
u_set m_rows_with_changed_bounds;
|
||||
unsigned_vector m_row_bounds_to_replay;
|
||||
|
||||
u_set m_basic_columns_with_changed_cost;
|
||||
u_set m_columns_with_changed_bounds;
|
||||
u_set m_rows_with_changed_bounds;
|
||||
unsigned_vector m_row_bounds_to_replay;
|
||||
|
||||
u_set m_basic_columns_with_changed_cost;
|
||||
// these are basic columns with the value changed, so the corresponding row in the tableau
|
||||
// does not sum to zero anymore
|
||||
u_set m_incorrect_columns;
|
||||
// copy of m_r_solver.inf_set()
|
||||
unsigned_vector m_inf_index_copy;
|
||||
stacked_value<unsigned> m_term_count;
|
||||
vector<lar_term*> m_terms;
|
||||
indexed_vector<mpq> m_column_buffer;
|
||||
u_set m_incorrect_columns;
|
||||
// copy of m_r_solver.inf_heap()
|
||||
unsigned_vector m_inf_index_copy;
|
||||
stacked_value<unsigned> m_term_count;
|
||||
vector<lar_term*> m_terms;
|
||||
indexed_vector<mpq> m_column_buffer;
|
||||
std::unordered_map<lar_term, std::pair<mpq, unsigned>, term_hasher, term_comparer>
|
||||
m_normalized_terms_to_columns;
|
||||
vector<impq> m_backup_x;
|
||||
stacked_vector<unsigned> m_usage_in_terms;
|
||||
m_normalized_terms_to_columns;
|
||||
vector<impq> m_backup_x;
|
||||
stacked_vector<unsigned> m_usage_in_terms;
|
||||
// ((x[j], is_int(j))->j) for fixed j, used in equalities propagation
|
||||
// maps values to integral fixed vars
|
||||
map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>> m_fixed_var_table_int;
|
||||
map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>> m_fixed_var_table_int;
|
||||
// maps values to non-integral fixed vars
|
||||
map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>> m_fixed_var_table_real;
|
||||
map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>> m_fixed_var_table_real;
|
||||
// end of fields
|
||||
|
||||
////////////////// methods ////////////////////////////////
|
||||
|
||||
static bool valid_index(unsigned j) { return static_cast<int>(j) >= 0;}
|
||||
const lar_term & get_term(unsigned j) const;
|
||||
|
||||
static bool valid_index(unsigned j) { return static_cast<int>(j) >= 0; }
|
||||
const lar_term& get_term(unsigned j) const;
|
||||
bool row_has_a_big_num(unsigned i) const;
|
||||
// init region
|
||||
bool strategy_is_undecided() const;
|
||||
void register_new_ext_var_index(unsigned ext_v, bool is_int);
|
||||
bool term_is_int(const lar_term * t) const;
|
||||
bool term_is_int(const vector<std::pair<mpq, unsigned int>> & coeffs) const;
|
||||
bool term_is_int(const lar_term* t) const;
|
||||
bool term_is_int(const vector<std::pair<mpq, unsigned int>>& coeffs) const;
|
||||
void add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int);
|
||||
void add_new_var_to_core_fields_for_mpq(bool register_in_basis);
|
||||
mpq adjust_bound_for_int(lpvar j, lconstraint_kind&, const mpq&);
|
||||
|
||||
// terms
|
||||
bool all_vars_are_registered(const vector<std::pair<mpq, var_index>> & coeffs);
|
||||
var_index add_term_undecided(const vector<std::pair<mpq, var_index>> & coeffs);
|
||||
bool term_coeffs_are_ok(const vector<std::pair<mpq, var_index>> & coeffs);
|
||||
bool all_vars_are_registered(const vector<std::pair<mpq, var_index>>& coeffs);
|
||||
var_index add_term_undecided(const vector<std::pair<mpq, var_index>>& coeffs);
|
||||
bool term_coeffs_are_ok(const vector<std::pair<mpq, var_index>>& coeffs);
|
||||
void push_term(lar_term* t);
|
||||
void add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index);
|
||||
void add_row_from_term_no_constraint(const lar_term* term, unsigned term_ext_index);
|
||||
void add_basic_var_to_core_fields();
|
||||
bool compare_values(impq const& lhs, lconstraint_kind k, const mpq & rhs);
|
||||
bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs);
|
||||
|
||||
inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.clear(); }
|
||||
inline void increase_by_one_columns_with_changed_bounds() { m_columns_with_changed_bounds.increase_size_by_one(); }
|
||||
inline void insert_to_columns_with_changed_bounds(unsigned j) { m_columns_with_changed_bounds.insert(j); }
|
||||
|
||||
void update_column_type_and_bound_check_on_equal(unsigned j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index, unsigned&);
|
||||
void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void update_column_type_and_bound_with_ub(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void update_column_type_and_bound_with_no_ub(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
|
||||
void insert_to_columns_with_changed_bounds(unsigned j);
|
||||
void update_column_type_and_bound_check_on_equal(unsigned j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index, unsigned&);
|
||||
void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void update_column_type_and_bound_with_ub(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void update_column_type_and_bound_with_no_ub(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index);
|
||||
void register_in_fixed_var_table(unsigned, unsigned&);
|
||||
void remove_non_fixed_from_fixed_var_table();
|
||||
constraint_index add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side);
|
||||
constraint_index add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq& right_side);
|
||||
inline void set_infeasible_column(unsigned j) {
|
||||
set_status(lp_status::INFEASIBLE);
|
||||
m_crossed_bounds_column = j;
|
||||
}
|
||||
constraint_index add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term,
|
||||
lconstraint_kind kind, const mpq & right_side);
|
||||
lconstraint_kind kind, const mpq& right_side);
|
||||
unsigned row_of_basic_column(unsigned) const;
|
||||
void decide_on_strategy_and_adjust_initial_state();
|
||||
void adjust_initial_state();
|
||||
void adjust_initial_state_for_tableau_rows();
|
||||
bool sizes_are_correct() const;
|
||||
bool implied_bound_is_correctly_explained(implied_bound const & be, const vector<std::pair<mpq, unsigned>> & explanation) const;
|
||||
|
||||
bool implied_bound_is_correctly_explained(implied_bound const& be, const vector<std::pair<mpq, unsigned>>& explanation) const;
|
||||
|
||||
void substitute_basis_var_in_terms_for_row(unsigned i);
|
||||
|
||||
|
||||
template <typename T>
|
||||
unsigned calculate_implied_bounds_for_row(unsigned row_index, lp_bound_propagator<T> & bp) {
|
||||
|
||||
if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation || row_has_a_big_num(row_index))
|
||||
unsigned calculate_implied_bounds_for_row(unsigned row_index, lp_bound_propagator<T>& bp) {
|
||||
if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation || row_has_a_big_num(row_index))
|
||||
return 0;
|
||||
|
||||
|
||||
return bound_analyzer_on_row<row_strip<mpq>, lp_bound_propagator<T>>::analyze_row(
|
||||
A_r().m_rows[row_index],
|
||||
null_ci,
|
||||
|
@ -177,27 +174,28 @@ class lar_solver : public column_namer {
|
|||
row_index,
|
||||
bp);
|
||||
}
|
||||
|
||||
|
||||
static void clean_popped_elements_for_heap(unsigned n, lpvar_heap& set);
|
||||
static void clean_popped_elements(unsigned n, u_set& set);
|
||||
bool maximize_term_on_tableau(const lar_term & term,
|
||||
impq &term_max);
|
||||
bool maximize_term_on_tableau(const lar_term& term,
|
||||
impq& term_max);
|
||||
bool costs_are_zeros_for_r_solver() const;
|
||||
bool reduced_costs_are_zeroes_for_r_solver() const;
|
||||
void set_costs_to_zero(const lar_term & term);
|
||||
void prepare_costs_for_r_solver(const lar_term & term);
|
||||
bool maximize_term_on_corrected_r_solver(lar_term & term, impq &term_max);
|
||||
void set_costs_to_zero(const lar_term& term);
|
||||
void prepare_costs_for_r_solver(const lar_term& term);
|
||||
bool maximize_term_on_corrected_r_solver(lar_term& term, impq& term_max);
|
||||
void pop_core_solver_params();
|
||||
void pop_core_solver_params(unsigned k);
|
||||
void set_upper_bound_witness(var_index j, constraint_index ci);
|
||||
void set_lower_bound_witness(var_index j, constraint_index ci);
|
||||
void substitute_terms_in_linear_expression( const vector<std::pair<mpq, var_index>>& left_side_with_terms,
|
||||
vector<std::pair<mpq, var_index>> &left_side) const;
|
||||
|
||||
void substitute_terms_in_linear_expression(const vector<std::pair<mpq, var_index>>& left_side_with_terms,
|
||||
vector<std::pair<mpq, var_index>>& left_side) const;
|
||||
|
||||
void detect_rows_of_bound_change_column_for_nbasic_column_tableau(unsigned j);
|
||||
bool use_tableau_costs() const;
|
||||
bool tableau_with_costs() const;
|
||||
bool costs_are_used() const;
|
||||
void change_basic_columns_dependend_on_a_given_nb_column(unsigned j, const numeric_pair<mpq> & delta);
|
||||
void change_basic_columns_dependend_on_a_given_nb_column(unsigned j, const numeric_pair<mpq>& delta);
|
||||
void update_x_and_inf_costs_for_column_with_changed_bounds(unsigned j);
|
||||
unsigned num_changed_bounds() const { return m_rows_with_changed_bounds.size(); }
|
||||
void insert_row_with_changed_bounds(unsigned rid);
|
||||
|
@ -209,19 +207,19 @@ class lar_solver : public column_namer {
|
|||
numeric_pair<mpq> get_basic_var_value_from_row(unsigned i);
|
||||
bool all_constrained_variables_are_registered(const vector<std::pair<mpq, var_index>>& left_side);
|
||||
bool all_constraints_hold() const;
|
||||
bool constraint_holds(const lar_base_constraint & constr, std::unordered_map<var_index, mpq> & var_map) const;
|
||||
static void register_in_map(std::unordered_map<var_index, mpq> & coeffs, const lar_base_constraint & cn, const mpq & a);
|
||||
static void register_monoid_in_map(std::unordered_map<var_index, mpq> & coeffs, const mpq & a, unsigned j);
|
||||
bool the_left_sides_sum_to_zero(const vector<std::pair<mpq, unsigned>> & evidence) const;
|
||||
bool constraint_holds(const lar_base_constraint& constr, std::unordered_map<var_index, mpq>& var_map) const;
|
||||
static void register_in_map(std::unordered_map<var_index, mpq>& coeffs, const lar_base_constraint& cn, const mpq& a);
|
||||
static void register_monoid_in_map(std::unordered_map<var_index, mpq>& coeffs, const mpq& a, unsigned j);
|
||||
bool the_left_sides_sum_to_zero(const vector<std::pair<mpq, unsigned>>& evidence) const;
|
||||
bool explanation_is_correct(explanation&) const;
|
||||
bool inf_explanation_is_correct() const;
|
||||
mpq sum_of_right_sides_of_explanation(explanation &) const;
|
||||
mpq sum_of_right_sides_of_explanation(explanation&) const;
|
||||
void get_infeasibility_explanation_for_inf_sign(
|
||||
explanation & exp,
|
||||
const vector<std::pair<mpq, unsigned>> & inf_row,
|
||||
explanation& exp,
|
||||
const vector<std::pair<mpq, unsigned>>& inf_row,
|
||||
int inf_sign) const;
|
||||
mpq get_left_side_val(const lar_base_constraint & cns, const std::unordered_map<var_index, mpq> & var_map) const;
|
||||
void fill_var_set_for_random_update(unsigned sz, var_index const * vars, vector<unsigned>& column_list);
|
||||
mpq get_left_side_val(const lar_base_constraint& cns, const std::unordered_map<var_index, mpq>& var_map) const;
|
||||
void fill_var_set_for_random_update(unsigned sz, var_index const* vars, vector<unsigned>& column_list);
|
||||
bool column_represents_row_in_tableau(unsigned j);
|
||||
void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j);
|
||||
void remove_last_row_and_column_from_tableau(unsigned j);
|
||||
|
@ -230,25 +228,25 @@ class lar_solver : public column_namer {
|
|||
void remove_last_column_from_basis_tableau(unsigned j);
|
||||
void remove_last_column_from_tableau();
|
||||
void pop_tableau();
|
||||
void clean_inf_set_of_r_solver_after_pop();
|
||||
void clean_inf_heap_of_r_solver_after_pop();
|
||||
inline bool column_value_is_integer(unsigned j) const { return get_column_value(j).is_int(); }
|
||||
bool model_is_int_feasible() const;
|
||||
|
||||
bool bound_is_integer_for_integer_column(unsigned j, const mpq & right_side) const;
|
||||
inline lar_core_solver & get_core_solver() { return m_mpq_lar_core_solver; }
|
||||
|
||||
bool bound_is_integer_for_integer_column(unsigned j, const mpq& right_side) const;
|
||||
inline lar_core_solver& get_core_solver() { return m_mpq_lar_core_solver; }
|
||||
var_index to_column(unsigned ext_j) const;
|
||||
void fix_terms_with_rounded_columns();
|
||||
bool remove_from_basis(unsigned);
|
||||
lar_term get_term_to_maximize(unsigned ext_j) const;
|
||||
bool sum_first_coords(const lar_term& t, mpq & val) const;
|
||||
bool sum_first_coords(const lar_term& t, mpq& val) const;
|
||||
void register_normalized_term(const lar_term&, lpvar);
|
||||
void deregister_normalized_term(const lar_term&);
|
||||
|
||||
mutable std::unordered_set<impq> m_set_of_different_pairs;
|
||||
mutable std::unordered_set<mpq> m_set_of_different_singles;
|
||||
mutable std::unordered_set<mpq> m_set_of_different_singles;
|
||||
mutable mpq m_delta;
|
||||
|
||||
public:
|
||||
public:
|
||||
// this function just looks at the status
|
||||
bool is_feasible() const;
|
||||
|
||||
|
@ -256,7 +254,6 @@ public:
|
|||
return m_fixed_var_table_int;
|
||||
}
|
||||
|
||||
|
||||
const map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>>& fixed_var_table_real() const {
|
||||
return m_fixed_var_table_real;
|
||||
}
|
||||
|
@ -265,11 +262,12 @@ public:
|
|||
return m_fixed_var_table_real;
|
||||
}
|
||||
|
||||
bool find_in_fixed_tables(const rational& mpq, bool is_int, unsigned & j) const {
|
||||
return is_int? fixed_var_table_int().find(mpq, j) : fixed_var_table_real().find(mpq, j);
|
||||
bool find_in_fixed_tables(const rational& mpq, bool is_int, unsigned& j) const {
|
||||
return is_int ? fixed_var_table_int().find(mpq, j) : fixed_var_table_real().find(mpq, j);
|
||||
}
|
||||
|
||||
template <typename T> void remove_non_fixed_from_table(T&);
|
||||
|
||||
template <typename T>
|
||||
void remove_non_fixed_from_table(T&);
|
||||
|
||||
unsigned external_to_column_index(unsigned) const;
|
||||
|
||||
|
@ -282,38 +280,38 @@ public:
|
|||
inline void set_column_value_test(unsigned j, const impq& v) {
|
||||
set_column_value(j, v);
|
||||
}
|
||||
|
||||
|
||||
var_index add_named_var(unsigned ext_j, bool is_integer, const std::string&);
|
||||
|
||||
lp_status maximize_term(unsigned j_or_term, impq &term_max);
|
||||
lp_status maximize_term(unsigned j_or_term, impq& term_max);
|
||||
|
||||
inline core_solver_pretty_printer<lp::mpq, lp::impq> pp(std::ostream& out) const {
|
||||
return core_solver_pretty_printer<lp::mpq, lp::impq>(m_mpq_lar_core_solver.m_r_solver, out);
|
||||
inline core_solver_pretty_printer<lp::mpq, lp::impq> pp(std::ostream& out) const {
|
||||
return core_solver_pretty_printer<lp::mpq, lp::impq>(m_mpq_lar_core_solver.m_r_solver, out);
|
||||
}
|
||||
|
||||
void get_infeasibility_explanation(explanation &) const;
|
||||
void get_infeasibility_explanation(explanation&) const;
|
||||
|
||||
inline void backup_x() { m_backup_x = m_mpq_lar_core_solver.m_r_x; }
|
||||
|
||||
inline void restore_x() { m_mpq_lar_core_solver.m_r_x = m_backup_x; }
|
||||
|
||||
template <typename T>
|
||||
void explain_implied_bound(const implied_bound & ib, lp_bound_propagator<T> & bp) {
|
||||
void explain_implied_bound(const implied_bound& ib, lp_bound_propagator<T>& bp) {
|
||||
unsigned i = ib.m_row_or_term_index;
|
||||
int bound_sign = (ib.m_is_lower_bound ? 1 : -1);
|
||||
int j_sign = (ib.m_coeff_before_j_is_pos ? 1 : -1) * bound_sign;
|
||||
unsigned bound_j = ib.m_j;
|
||||
if (tv::is_term(bound_j))
|
||||
if (tv::is_term(bound_j))
|
||||
bound_j = m_var_register.external_to_local(bound_j);
|
||||
|
||||
for (auto const& r : get_row(i)) {
|
||||
unsigned j = r.var();
|
||||
if (j == bound_j)
|
||||
if (j == bound_j)
|
||||
continue;
|
||||
mpq const& a = r.coeff();
|
||||
int a_sign = is_pos(a) ? 1 : -1;
|
||||
int sign = j_sign * a_sign;
|
||||
const ul_pair & ul = m_columns_to_ul_pairs[j];
|
||||
const ul_pair& ul = m_columns_to_ul_pairs[j];
|
||||
auto witness = sign > 0 ? ul.upper_bound_witness() : ul.lower_bound_witness();
|
||||
lp_assert(is_valid(witness));
|
||||
bp.consume(a, witness);
|
||||
|
@ -327,13 +325,13 @@ public:
|
|||
}
|
||||
|
||||
// lp_assert(implied_bound_is_correctly_explained(ib, explanation)); }
|
||||
constraint_index mk_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side);
|
||||
constraint_index mk_var_bound(var_index j, lconstraint_kind kind, const mpq& right_side);
|
||||
void activate_check_on_equal(constraint_index, var_index&);
|
||||
void activate(constraint_index);
|
||||
void random_update(unsigned sz, var_index const * vars);
|
||||
void random_update(unsigned sz, var_index const* vars);
|
||||
void mark_rows_for_bound_prop(lpvar j);
|
||||
template <typename T>
|
||||
void propagate_bounds_for_touched_rows(lp_bound_propagator<T> & bp) {
|
||||
void propagate_bounds_for_touched_rows(lp_bound_propagator<T>& bp) {
|
||||
unsigned num_prop = 0;
|
||||
for (unsigned i : m_rows_with_changed_bounds) {
|
||||
num_prop += calculate_implied_bounds_for_row(i, bp);
|
||||
|
@ -347,7 +345,7 @@ public:
|
|||
bp.clear_for_eq();
|
||||
for (unsigned i : m_rows_with_changed_bounds) {
|
||||
unsigned offset_eqs = stats().m_offset_eqs;
|
||||
bp.cheap_eq_tree(i);
|
||||
bp.cheap_eq_tree(i);
|
||||
if (settings().get_cancel_flag())
|
||||
return;
|
||||
if (stats().m_offset_eqs > offset_eqs)
|
||||
|
@ -358,74 +356,74 @@ public:
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void check_missed_propagations(lp_bound_propagator<T> & bp) {
|
||||
for (unsigned i = 0; i < A_r().row_count(); i++)
|
||||
if (!m_rows_with_changed_bounds.contains(i))
|
||||
void check_missed_propagations(lp_bound_propagator<T>& bp) {
|
||||
for (unsigned i = 0; i < A_r().row_count(); i++)
|
||||
if (!m_rows_with_changed_bounds.contains(i))
|
||||
if (0 < calculate_implied_bounds_for_row(i, bp)) {
|
||||
verbose_stream() << i << ": " << get_row(i) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool is_fixed_at_bound(column_index const& j);
|
||||
bool has_fixed_at_bound();
|
||||
|
||||
bool is_fixed(column_index const& j) const { return column_is_fixed(j); }
|
||||
bool is_fixed(column_index const& j) const { return column_is_fixed(j); }
|
||||
inline column_index to_column_index(unsigned v) const { return column_index(external_to_column_index(v)); }
|
||||
bool external_is_used(unsigned) const;
|
||||
void pop(unsigned k);
|
||||
bool compare_values(var_index j, lconstraint_kind kind, const mpq & right_side);
|
||||
var_index add_term(const vector<std::pair<mpq, var_index>> & coeffs, unsigned ext_i);
|
||||
bool compare_values(var_index j, lconstraint_kind kind, const mpq& right_side);
|
||||
var_index add_term(const vector<std::pair<mpq, var_index>>& coeffs, unsigned ext_i);
|
||||
void register_existing_terms();
|
||||
constraint_index add_var_bound(var_index, lconstraint_kind, const mpq &);
|
||||
constraint_index add_var_bound_check_on_equal(var_index, lconstraint_kind, const mpq &, var_index&);
|
||||
|
||||
var_index ensure_column(var_index vi);
|
||||
constraint_index add_var_bound(var_index, lconstraint_kind, const mpq&);
|
||||
constraint_index add_var_bound_check_on_equal(var_index, lconstraint_kind, const mpq&, var_index&);
|
||||
|
||||
var_index add_var(unsigned ext_j, bool is_integer);
|
||||
void set_cut_strategy(unsigned cut_frequency);
|
||||
inline unsigned column_count() const { return A_r().column_count(); }
|
||||
inline var_index local_to_external(var_index idx) const {
|
||||
return tv::is_term(idx)?
|
||||
m_term_register.local_to_external(idx) : m_var_register.local_to_external(idx);
|
||||
return tv::is_term(idx) ? m_term_register.local_to_external(idx) : m_var_register.local_to_external(idx);
|
||||
}
|
||||
bool column_corresponds_to_term(unsigned) const;
|
||||
const lar_term& column_to_term(unsigned j) const {
|
||||
SASSERT(column_corresponds_to_term(j));
|
||||
return get_term(column2tv(to_column_index(j)));
|
||||
}
|
||||
|
||||
inline unsigned row_count() const { return A_r().row_count(); }
|
||||
bool var_is_registered(var_index vj) const;
|
||||
void clear_inf_set() {
|
||||
m_mpq_lar_core_solver.m_r_solver.inf_set().clear();
|
||||
void clear_inf_heap() {
|
||||
m_mpq_lar_core_solver.m_r_solver.inf_heap().clear();
|
||||
}
|
||||
inline void remove_column_from_inf_set(unsigned j) {
|
||||
m_mpq_lar_core_solver.m_r_solver.remove_column_from_inf_set(j);
|
||||
|
||||
void pivot(int entering, int leaving) {
|
||||
m_mpq_lar_core_solver.pivot(entering, leaving);
|
||||
}
|
||||
|
||||
template <typename ChangeReport>
|
||||
void change_basic_columns_dependend_on_a_given_nb_column_report(unsigned j,
|
||||
const numeric_pair<mpq> & delta,
|
||||
const numeric_pair<mpq>& delta,
|
||||
const ChangeReport& after) {
|
||||
|
||||
for (const auto & c : A_r().m_columns[j]) {
|
||||
unsigned bj = m_mpq_lar_core_solver.m_r_basis[c.var()];
|
||||
if (tableau_with_costs()) {
|
||||
m_basic_columns_with_changed_cost.insert(bj);
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_solver.add_delta_to_x_and_track_feasibility(bj, - A_r().get_val(c) * delta);
|
||||
after(bj);
|
||||
TRACE("change_x_del",
|
||||
tout << "changed basis column " << bj << ", it is " <<
|
||||
( m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj)? "feas":"inf") << std::endl;);
|
||||
}
|
||||
}
|
||||
for (const auto& c : A_r().m_columns[j]) {
|
||||
unsigned bj = m_mpq_lar_core_solver.m_r_basis[c.var()];
|
||||
if (tableau_with_costs())
|
||||
m_basic_columns_with_changed_cost.insert(bj);
|
||||
m_mpq_lar_core_solver.m_r_solver.add_delta_to_x_and_track_feasibility(bj, -A_r().get_val(c) * delta);
|
||||
after(bj);
|
||||
TRACE("change_x_del",
|
||||
tout << "changed basis column " << bj << ", it is " << (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj) ? "feas" : "inf") << std::endl;);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ChangeReport>
|
||||
void set_value_for_nbasic_column_report(unsigned j,
|
||||
const impq & new_val,
|
||||
const impq& new_val,
|
||||
const ChangeReport& after) {
|
||||
|
||||
lp_assert(!is_base(j));
|
||||
auto & x = m_mpq_lar_core_solver.m_r_x[j];
|
||||
auto& x = m_mpq_lar_core_solver.m_r_x[j];
|
||||
auto delta = new_val - x;
|
||||
x = new_val;
|
||||
after(j);
|
||||
change_basic_columns_dependend_on_a_given_nb_column_report(j, delta, after);
|
||||
}
|
||||
|
||||
|
||||
template <typename Blocker, typename ChangeReport>
|
||||
bool try_to_patch(lpvar j, const mpq& val,
|
||||
const Blocker& is_blocked,
|
||||
|
@ -442,8 +440,8 @@ public:
|
|||
impq delta = get_column_value(j) - ival;
|
||||
for (auto c : A_r().column(j)) {
|
||||
unsigned row_index = c.var();
|
||||
const mpq & a = c.coeff();
|
||||
unsigned rj = m_mpq_lar_core_solver.m_r_basis[row_index];
|
||||
const mpq& a = c.coeff();
|
||||
unsigned rj = m_mpq_lar_core_solver.m_r_basis[row_index];
|
||||
impq rj_new_val = a * delta + get_column_value(rj);
|
||||
// if (column_is_int(rj) && !rj_new_val.is_int())
|
||||
// return false;
|
||||
|
@ -460,65 +458,63 @@ public:
|
|||
|
||||
inline bool column_has_lower_bound(unsigned j) const {
|
||||
return m_mpq_lar_core_solver.m_r_solver.column_has_lower_bound(j);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
constraint_index get_column_upper_bound_witness(unsigned j) const {
|
||||
inline constraint_index get_column_upper_bound_witness(unsigned j) const {
|
||||
if (tv::is_term(j)) {
|
||||
j = m_var_register.external_to_local(j);
|
||||
}
|
||||
return m_columns_to_ul_pairs()[j].upper_bound_witness();
|
||||
}
|
||||
|
||||
inline
|
||||
const impq& get_upper_bound(column_index j) const {
|
||||
inline const impq& get_upper_bound(column_index j) const {
|
||||
return m_mpq_lar_core_solver.m_r_solver.m_upper_bounds[j];
|
||||
}
|
||||
|
||||
inline
|
||||
const impq& get_lower_bound(column_index j) const {
|
||||
inline const impq& get_lower_bound(column_index j) const {
|
||||
return m_mpq_lar_core_solver.m_r_solver.m_lower_bounds[j];
|
||||
}
|
||||
bool has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const;
|
||||
bool has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const;
|
||||
bool has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const;
|
||||
bool has_value(var_index var, mpq& value) const;
|
||||
bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>& ) const;
|
||||
bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>&) const;
|
||||
unsigned map_term_index_to_column_index(unsigned j) const;
|
||||
bool column_is_fixed(unsigned j) const;
|
||||
bool column_is_free(unsigned j) const;
|
||||
bool column_is_feasible(unsigned j) const { return m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j);}
|
||||
unsigned column_to_reported_index(unsigned j) const;
|
||||
lp_settings & settings();
|
||||
lp_settings const & settings() const;
|
||||
lp_settings& settings();
|
||||
lp_settings const& settings() const;
|
||||
statistics& stats();
|
||||
|
||||
|
||||
void updt_params(params_ref const& p);
|
||||
column_type get_column_type(unsigned j) const { return m_mpq_lar_core_solver.m_column_types()[j]; }
|
||||
const impq & get_lower_bound(unsigned j) const { return m_mpq_lar_core_solver.m_r_lower_bounds()[j]; }
|
||||
const impq & get_upper_bound(unsigned j) const { return m_mpq_lar_core_solver.m_r_upper_bounds()[j]; }
|
||||
const impq& get_lower_bound(unsigned j) const { return m_mpq_lar_core_solver.m_r_lower_bounds()[j]; }
|
||||
const impq& get_upper_bound(unsigned j) const { return m_mpq_lar_core_solver.m_r_upper_bounds()[j]; }
|
||||
std::ostream& print_terms(std::ostream& out) const;
|
||||
std::ostream& print_term(lar_term const& term, std::ostream & out) const;
|
||||
static std::ostream& print_term_as_indices(lar_term const& term, std::ostream & out);
|
||||
std::ostream& print_constraint_indices_only(const lar_base_constraint * c, std::ostream & out) const;
|
||||
std::ostream& print_implied_bound(const implied_bound& be, std::ostream & out) const;
|
||||
std::ostream& print_term(lar_term const& term, std::ostream& out) const;
|
||||
static std::ostream& print_term_as_indices(lar_term const& term, std::ostream& out);
|
||||
std::ostream& print_constraint_indices_only(const lar_base_constraint* c, std::ostream& out) const;
|
||||
std::ostream& print_implied_bound(const implied_bound& be, std::ostream& out) const;
|
||||
std::ostream& print_values(std::ostream& out) const;
|
||||
std::ostream& display(std::ostream& out) const;
|
||||
|
||||
bool init_model() const;
|
||||
mpq get_value(column_index const& j) const;
|
||||
mpq get_tv_value(tv const& t) const;
|
||||
const impq & get_tv_ivalue(tv const& t) const;
|
||||
void get_model(std::unordered_map<var_index, mpq> & variable_values) const;
|
||||
const impq& get_tv_ivalue(tv const& t) const;
|
||||
void get_model(std::unordered_map<var_index, mpq>& variable_values) const;
|
||||
void get_rid_of_inf_eps();
|
||||
void get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq> & variable_values) const;
|
||||
void get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq>& variable_values) const;
|
||||
std::string get_variable_name(var_index vi) const override;
|
||||
void set_variable_name(var_index vi, std::string);
|
||||
inline unsigned number_of_vars() const { return m_var_register.size(); }
|
||||
inline bool is_base(unsigned j) const { return m_mpq_lar_core_solver.m_r_heading[j] >= 0; }
|
||||
inline const impq & column_lower_bound(unsigned j) const {
|
||||
inline const impq& column_lower_bound(unsigned j) const {
|
||||
return m_mpq_lar_core_solver.lower_bound(j);
|
||||
}
|
||||
|
||||
inline const impq & column_upper_bound(unsigned j) const {
|
||||
inline const impq& column_upper_bound(unsigned j) const {
|
||||
return m_mpq_lar_core_solver.upper_bound(j);
|
||||
}
|
||||
|
||||
|
@ -531,9 +527,9 @@ public:
|
|||
}
|
||||
|
||||
std::pair<constraint_index, constraint_index> add_equality(lpvar j, lpvar k);
|
||||
|
||||
inline void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index & lc, constraint_index & uc) const {
|
||||
const ul_pair & ul = m_columns_to_ul_pairs[j];
|
||||
|
||||
inline void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index& lc, constraint_index& uc) const {
|
||||
const ul_pair& ul = m_columns_to_ul_pairs[j];
|
||||
lc = ul.lower_bound_witness();
|
||||
uc = ul.upper_bound_witness();
|
||||
}
|
||||
|
@ -550,19 +546,19 @@ public:
|
|||
inline tv column2tv(column_index const& c) const {
|
||||
return tv::raw(column_to_reported_index(c));
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& print_column_info(unsigned j, std::ostream& out) const {
|
||||
m_mpq_lar_core_solver.m_r_solver.print_column_info(j, out);
|
||||
if (tv::is_term(j)) {
|
||||
print_term_as_indices(get_term(j), out) << "\n";
|
||||
|
||||
} else if (column_corresponds_to_term(j)) {
|
||||
|
||||
} else if (column_corresponds_to_term(j)) {
|
||||
const lar_term& t = get_term(m_var_register.local_to_external(j));
|
||||
print_term_as_indices(t, out) << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void subst_known_terms(lar_term*);
|
||||
|
||||
inline std::ostream& print_column_bound_info(unsigned j, std::ostream& out) const {
|
||||
|
@ -573,67 +569,68 @@ public:
|
|||
|
||||
inline bool has_inf_int() const {
|
||||
for (unsigned j = 0; j < column_count(); j++) {
|
||||
if (column_is_int(j) && ! column_value_is_int(j))
|
||||
if (column_is_int(j) && !column_value_is_int(j))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline const vector<lar_term*> & terms() const { return m_terms; }
|
||||
inline const vector<lar_term*>& terms() const { return m_terms; }
|
||||
inline lar_term const& term(unsigned i) const { return *m_terms[i]; }
|
||||
inline void set_int_solver(int_solver * int_slv) { m_int_solver = int_slv; }
|
||||
inline int_solver * get_int_solver() { return m_int_solver; }
|
||||
inline const int_solver * get_int_solver() const { return m_int_solver; }
|
||||
inline const lar_term & get_term(tv const& t) const { lp_assert(t.is_term()); return *m_terms[t.id()]; }
|
||||
lp_status find_feasible_solution();
|
||||
inline void set_int_solver(int_solver* int_slv) { m_int_solver = int_slv; }
|
||||
inline int_solver* get_int_solver() { return m_int_solver; }
|
||||
inline const int_solver* get_int_solver() const { return m_int_solver; }
|
||||
inline const lar_term& get_term(tv const& t) const {
|
||||
lp_assert(t.is_term());
|
||||
return *m_terms[t.id()];
|
||||
}
|
||||
lp_status find_feasible_solution();
|
||||
void move_non_basic_columns_to_bounds(bool);
|
||||
bool move_non_basic_column_to_bounds(unsigned j, bool);
|
||||
inline bool r_basis_has_inf_int() const {
|
||||
for (unsigned j : r_basis()) {
|
||||
if (column_is_int(j) && ! column_value_is_int(j))
|
||||
if (column_is_int(j) && !column_value_is_int(j))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void round_to_integer_solution();
|
||||
inline const row_strip<mpq> & get_row(unsigned i) const { return A_r().m_rows[i]; }
|
||||
inline const row_strip<mpq> & basic2row(unsigned i) const { return A_r().m_rows[row_of_basic_column(i)]; }
|
||||
inline const column_strip & get_column(unsigned i) const { return A_r().m_columns[i]; }
|
||||
inline const row_strip<mpq>& get_row(unsigned i) const { return A_r().m_rows[i]; }
|
||||
inline const row_strip<mpq>& basic2row(unsigned i) const { return A_r().m_rows[row_of_basic_column(i)]; }
|
||||
inline const column_strip& get_column(unsigned i) const { return A_r().m_columns[i]; }
|
||||
bool row_is_correct(unsigned i) const;
|
||||
bool ax_is_correct() const;
|
||||
bool get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq &rs, constraint_index& ci, bool &upper_bound) const;
|
||||
bool get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, constraint_index& ci, bool& upper_bound) const;
|
||||
bool var_is_int(var_index v) const;
|
||||
inline const vector<int> & r_heading() const { return m_mpq_lar_core_solver.m_r_heading; }
|
||||
inline const vector<unsigned> & r_basis() const { return m_mpq_lar_core_solver.r_basis(); }
|
||||
inline const vector<unsigned> & r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); }
|
||||
inline bool column_is_real(unsigned j) const { return !column_is_int(j); }
|
||||
inline const vector<int>& r_heading() const { return m_mpq_lar_core_solver.m_r_heading; }
|
||||
inline const vector<unsigned>& r_basis() const { return m_mpq_lar_core_solver.r_basis(); }
|
||||
inline const vector<unsigned>& r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); }
|
||||
inline bool column_is_real(unsigned j) const { return !column_is_int(j); }
|
||||
lp_status get_status() const;
|
||||
bool has_changed_columns() const { return !m_columns_with_changed_bounds.empty(); }
|
||||
bool has_changed_columns() const { return !m_columns_with_changed_bounds.empty(); }
|
||||
void set_status(lp_status s);
|
||||
lp_status solve();
|
||||
void fill_explanation_from_crossed_bounds_column(explanation & evidence) const;
|
||||
void fill_explanation_from_crossed_bounds_column(explanation& evidence) const;
|
||||
bool term_is_used_as_row(unsigned term) const;
|
||||
bool tighten_term_bounds_by_delta(tv const& t, const impq&);
|
||||
lar_solver();
|
||||
void set_track_pivoted_rows(bool v);
|
||||
bool get_track_pivoted_rows() const;
|
||||
bool get_track_pivoted_rows() const;
|
||||
~lar_solver() override;
|
||||
const vector<impq>& r_x() const { return m_mpq_lar_core_solver.m_r_x; }
|
||||
bool column_is_int(unsigned j) const;
|
||||
inline bool column_value_is_int(unsigned j) const { return m_mpq_lar_core_solver.m_r_x[j].is_int(); }
|
||||
inline static_matrix<mpq, impq> & A_r() { return m_mpq_lar_core_solver.m_r_A; }
|
||||
inline const static_matrix<mpq, impq> & A_r() const { return m_mpq_lar_core_solver.m_r_A; }
|
||||
inline static_matrix<mpq, impq>& A_r() { return m_mpq_lar_core_solver.m_r_A; }
|
||||
inline const static_matrix<mpq, impq>& A_r() const { return m_mpq_lar_core_solver.m_r_A; }
|
||||
// columns
|
||||
bool column_is_int(column_index const& j) const { return column_is_int((unsigned)j); }
|
||||
// const impq& get_ivalue(column_index const& j) const { return get_column_value(j); }
|
||||
// const impq& get_ivalue(column_index const& j) const { return get_column_value(j); }
|
||||
const impq& get_column_value(column_index const& j) const { return m_mpq_lar_core_solver.m_r_x[j]; }
|
||||
inline
|
||||
var_index external_to_local(unsigned j) const {
|
||||
inline var_index external_to_local(unsigned j) const {
|
||||
var_index local_j;
|
||||
if (m_var_register.external_is_used(j, local_j) ||
|
||||
m_term_register.external_is_used(j, local_j)) {
|
||||
return local_j;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -644,6 +641,5 @@ public:
|
|||
}
|
||||
friend int_solver;
|
||||
friend int_branch;
|
||||
|
||||
};
|
||||
}
|
||||
} // namespace lp
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
--*/
|
||||
// clang-format off
|
||||
#pragma once
|
||||
#include "math/lp/indexed_vector.h"
|
||||
#include "util/map.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue