diff options
author | Tim King <taking@cs.nyu.edu> | 2012-04-17 16:07:22 +0000 |
---|---|---|
committer | Tim King <taking@cs.nyu.edu> | 2012-04-17 16:07:22 +0000 |
commit | ccd77233892ace44fd4852999e66534d1c2283ea (patch) | |
tree | a856cacd24508a5839fcdbe728583ff055b64e34 /src | |
parent | 9644b6e12fbd3b649daafa43c5400d272e27bfb4 (diff) |
Merges branches/arithmetic/atom-database r2979 through 3247 into trunk. Below is a highlight of the changes:
- This introduces a new normal form to arithmetic.
-- Equalities and disequalities are in solved form.
Roughly speaking this means: (= x (+ y z)) is in normal form.
(See the comments in normal_form.h for what this formally requires.)
-- The normal form for inequality atoms always uses GEQ and GT instead of GEQ and LEQ.
Integer atoms always use GEQ.
- Constraint was added to TheoryArith.
-- A constraint is a triple of (k x v) where:
--- k is the type of the constraint (either LowerBound, UpperBound, Equality or Disequality),
--- x is an ArithVar, and
--- v is a DeltaRational value.
-- Constraints are always attached to a ConstraintDatabase.
-- A Constraint has its negation in the ConstraintDatabase [at least for now].
-- Every constraint belongs to a set of constraints for each ArithVar sorted by the delta rational values.
-- This set can be iterated over and provides efficient access to other constraints for this variable.
-- A literal may be attached to a constraint.
-- Constraints with attached literals may be marked as being asserted to the theory (sat context dependent).
-- Constraints can be propagated.
-- Every constraint has a proof (sat context dependent).
-- Proofs can be explained for either conflicts or propagations (if the node was propagated). (These proofs may be different.)
-- Equalities and disequalities can be marked as being split (user context dependent)
- This removes and replaces:
-- src/theory/arith/arith_prop_manager.*
-- src/theory/arith/atom_database.*
-- src/theory/arith/ordered_set.h
- Added isZero(), isOne() and isNegativeOne() to Rational and Integer.
- Added operator+ to CDList::const_iterator.
- Added const_iterator to CDQueue.
- Changes to regression tests.
Diffstat (limited to 'src')
48 files changed, 4764 insertions, 3170 deletions
diff --git a/src/context/cdlist.h b/src/context/cdlist.h index c22d617b0..9d7709589 100644 --- a/src/context/cdlist.h +++ b/src/context/cdlist.h @@ -384,6 +384,16 @@ public: /** Prefix decrement */ const_iterator& operator--() { --d_it; return *this; } + /** operator+ */ + const_iterator operator+(long signed int off) const { + return const_iterator(d_it + off); + } + + /** operator+ */ + const_iterator operator+(long unsigned int off) const { + return const_iterator(d_it + off); + } + // Postfix operations on iterators: requires a Proxy object to // hold the intermediate value for dereferencing class Proxy { diff --git a/src/context/cdqueue.h b/src/context/cdqueue.h index d8f6c42f1..b43217cfe 100644 --- a/src/context/cdqueue.h +++ b/src/context/cdqueue.h @@ -151,6 +151,16 @@ public: return ParentType::d_list[ParentType::d_size - 1]; } + typedef typename ParentType::const_iterator const_iterator; + + const_iterator begin() const { + return ParentType::begin() + d_iter; + } + + const_iterator end() const { + return ParentType::end(); + } + };/* class CDQueue<> */ }/* CVC4::context namespace */ diff --git a/src/context/cdtrail_queue.h b/src/context/cdtrail_queue.h index 3f6887d29..94d758ced 100644 --- a/src/context/cdtrail_queue.h +++ b/src/context/cdtrail_queue.h @@ -80,11 +80,15 @@ public: d_iter = d_iter + 1; } - const T& operator[](size_t index){ + const T& operator[](size_t index) const{ Assert(index < d_list.size()); return d_list[index]; } + size_t size() const{ + return d_list.size(); + } + };/* class CDTrailQueue<> */ }/* CVC4::context namespace */ diff --git a/src/prop/cryptominisat/MTRand/Makefile.in b/src/prop/cryptominisat/MTRand/Makefile.in index 1693a70f2..8cc478cdf 100644 --- a/src/prop/cryptominisat/MTRand/Makefile.in +++ b/src/prop/cryptominisat/MTRand/Makefile.in @@ -34,36 +34,17 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -target_triplet = @target@ -subdir = src/prop/cryptominisat/MTRand +subdir = MTRand DIST_COMMON = $(pkgincludesub_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/antlr.m4 \ - $(top_srcdir)/config/ax_prog_doxygen.m4 \ - $(top_srcdir)/config/ax_tls.m4 \ - $(top_srcdir)/config/bindings.m4 $(top_srcdir)/config/boost.m4 \ - $(top_srcdir)/config/cudd.m4 $(top_srcdir)/config/cvc4.m4 \ - $(top_srcdir)/config/gcc_version.m4 \ - $(top_srcdir)/config/libtool.m4 \ - $(top_srcdir)/config/ltoptions.m4 \ - $(top_srcdir)/config/ltsugar.m4 \ - $(top_srcdir)/config/ltversion.m4 \ - $(top_srcdir)/config/lt~obsolete.m4 \ - $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/readline.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/cvc4autoconfig.h +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -am__v_at_0 = @ SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -94,128 +75,54 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -ANTLR = @ANTLR@ -ANTLR_HOME = @ANTLR_HOME@ -ANTLR_INCLUDES = @ANTLR_INCLUDES@ -ANTLR_LDFLAGS = @ANTLR_LDFLAGS@ AR = @AR@ -AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDPATH = @BOOST_LDPATH@ -BOOST_ROOT = @BOOST_ROOT@ -BOOST_THREAD_LDFLAGS = @BOOST_THREAD_LDFLAGS@ -BOOST_THREAD_LDPATH = @BOOST_THREAD_LDPATH@ -BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ -BUILDING_SHARED = @BUILDING_SHARED@ -BUILDING_STATIC = @BUILDING_STATIC@ -CAMLP4O = @CAMLP4O@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CLN_CFLAGS = @CLN_CFLAGS@ -CLN_LIBS = @CLN_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CSHARP_CPPFLAGS = @CSHARP_CPPFLAGS@ -CUDD_CPPFLAGS = @CUDD_CPPFLAGS@ -CUDD_LDFLAGS = @CUDD_LDFLAGS@ -CUDD_LIBS = @CUDD_LIBS@ -CVC4_BINDINGS_LIBRARY_VERSION = @CVC4_BINDINGS_LIBRARY_VERSION@ -CVC4_BUILD_LIBCOMPAT = @CVC4_BUILD_LIBCOMPAT@ -CVC4_COMPAT_LIBRARY_VERSION = @CVC4_COMPAT_LIBRARY_VERSION@ -CVC4_HAS_THREADS = @CVC4_HAS_THREADS@ -CVC4_LANGUAGE_BINDINGS = @CVC4_LANGUAGE_BINDINGS@ -CVC4_LIBRARY_VERSION = @CVC4_LIBRARY_VERSION@ -CVC4_PARSER_LIBRARY_VERSION = @CVC4_PARSER_LIBRARY_VERSION@ -CVC4_TLS = @CVC4_TLS@ -CVC4_TLS_SUPPORTED = @CVC4_TLS_SUPPORTED@ -CVC4_USE_CLN_IMP = @CVC4_USE_CLN_IMP@ -CVC4_USE_GMP_IMP = @CVC4_USE_GMP_IMP@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ -CXXTEST = @CXXTEST@ -CXXTESTGEN = @CXXTESTGEN@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ -DOXYGEN_EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@ -DOXYGEN_EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@ -DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ -DX_CONFIG = @DX_CONFIG@ -DX_DOCDIR = @DX_DOCDIR@ -DX_DOT = @DX_DOT@ -DX_DOXYGEN = @DX_DOXYGEN@ -DX_DVIPS = @DX_DVIPS@ -DX_EGREP = @DX_EGREP@ -DX_ENV = @DX_ENV@ -DX_FLAG_DX_CURRENT_FEATURE = @DX_FLAG_DX_CURRENT_FEATURE@ -DX_FLAG_chi = @DX_FLAG_chi@ -DX_FLAG_chm = @DX_FLAG_chm@ -DX_FLAG_doc = @DX_FLAG_doc@ -DX_FLAG_dot = @DX_FLAG_dot@ -DX_FLAG_html = @DX_FLAG_html@ -DX_FLAG_man = @DX_FLAG_man@ -DX_FLAG_pdf = @DX_FLAG_pdf@ -DX_FLAG_ps = @DX_FLAG_ps@ -DX_FLAG_rtf = @DX_FLAG_rtf@ -DX_FLAG_xml = @DX_FLAG_xml@ -DX_HHC = @DX_HHC@ -DX_LATEX = @DX_LATEX@ -DX_MAKEINDEX = @DX_MAKEINDEX@ -DX_PDFLATEX = @DX_PDFLATEX@ -DX_PERL = @DX_PERL@ -DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ -FLAG_VISIBILITY_HIDDEN = @FLAG_VISIBILITY_HIDDEN@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JAR = @JAR@ -JAVA = @JAVA@ -JAVAC = @JAVAC@ -JAVAH = @JAVAH@ -JAVA_CPPFLAGS = @JAVA_CPPFLAGS@ LD = @LD@ LDFLAGS = @LDFLAGS@ -LFSC = @LFSC@ -LFSCARGS = @LFSCARGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ -MAN_DATE = @MAN_DATE@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OCAMLC = @OCAMLC@ -OCAMLFIND = @OCAMLFIND@ -OCAMLMKTOP = @OCAMLMKTOP@ +OPENMP_CXXFLAGS = @OPENMP_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -226,33 +133,12 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PERL = @PERL@ -PERL_CPPFLAGS = @PERL_CPPFLAGS@ -PHP_CPPFLAGS = @PHP_CPPFLAGS@ -PKG_CONFIG = @PKG_CONFIG@ -PYTHON = @PYTHON@ -PYTHON_CONFIG = @PYTHON_CONFIG@ -PYTHON_CXXFLAGS = @PYTHON_CXXFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDE = @PYTHON_INCLUDE@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ -RUBY_CPPFLAGS = @RUBY_CPPFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_BINARY = @STATIC_BINARY@ STRIP = @STRIP@ -SWIG = @SWIG@ -TCL_CPPFLAGS = @TCL_CPPFLAGS@ -TEST_CPPFLAGS = @TEST_CPPFLAGS@ -TEST_CXXFLAGS = @TEST_CXXFLAGS@ -TEST_LDFLAGS = @TEST_LDFLAGS@ VERSION = @VERSION@ -WNO_CONVERSION_NULL = @WNO_CONVERSION_NULL@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -292,26 +178,17 @@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ -mk_include = @mk_include@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ -target = @target@ target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @@ -320,7 +197,7 @@ pkgincludesub_HEADERS = MersenneTwister.h all: all-am .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -329,9 +206,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/prop/cryptominisat/MTRand/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu MTRand/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/prop/cryptominisat/MTRand/Makefile + $(AUTOMAKE) --gnu MTRand/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -345,9 +222,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) +$(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): diff --git a/src/prop/cryptominisat/Makefile.in b/src/prop/cryptominisat/Makefile.in index a6806f0b4..2d9ee8bf8 100644 --- a/src/prop/cryptominisat/Makefile.in +++ b/src/prop/cryptominisat/Makefile.in @@ -33,37 +33,21 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -target_triplet = @target@ -subdir = src/prop/cryptominisat -DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - AUTHORS INSTALL NEWS TODO config.guess config.sub depcomp \ - install-sh ltmain.sh missing +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure AUTHORS INSTALL NEWS TODO config.guess \ + config.sub depcomp install-sh ltmain.sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/antlr.m4 \ - $(top_srcdir)/config/ax_prog_doxygen.m4 \ - $(top_srcdir)/config/ax_tls.m4 \ - $(top_srcdir)/config/bindings.m4 $(top_srcdir)/config/boost.m4 \ - $(top_srcdir)/config/cudd.m4 $(top_srcdir)/config/cvc4.m4 \ - $(top_srcdir)/config/gcc_version.m4 \ - $(top_srcdir)/config/libtool.m4 \ - $(top_srcdir)/config/ltoptions.m4 \ - $(top_srcdir)/config/ltsugar.m4 \ - $(top_srcdir)/config/ltversion.m4 \ - $(top_srcdir)/config/lt~obsolete.m4 \ - $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/readline.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/cvc4autoconfig.h +CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -am__v_at_0 = @ SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ @@ -77,11 +61,17 @@ RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir + distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ @@ -107,130 +97,60 @@ am__relativize = \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -ANTLR = @ANTLR@ -ANTLR_HOME = @ANTLR_HOME@ -ANTLR_INCLUDES = @ANTLR_INCLUDES@ -ANTLR_LDFLAGS = @ANTLR_LDFLAGS@ AR = @AR@ -AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDPATH = @BOOST_LDPATH@ -BOOST_ROOT = @BOOST_ROOT@ -BOOST_THREAD_LDFLAGS = @BOOST_THREAD_LDFLAGS@ -BOOST_THREAD_LDPATH = @BOOST_THREAD_LDPATH@ -BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ -BUILDING_SHARED = @BUILDING_SHARED@ -BUILDING_STATIC = @BUILDING_STATIC@ -CAMLP4O = @CAMLP4O@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CLN_CFLAGS = @CLN_CFLAGS@ -CLN_LIBS = @CLN_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CSHARP_CPPFLAGS = @CSHARP_CPPFLAGS@ -CUDD_CPPFLAGS = @CUDD_CPPFLAGS@ -CUDD_LDFLAGS = @CUDD_LDFLAGS@ -CUDD_LIBS = @CUDD_LIBS@ -CVC4_BINDINGS_LIBRARY_VERSION = @CVC4_BINDINGS_LIBRARY_VERSION@ -CVC4_BUILD_LIBCOMPAT = @CVC4_BUILD_LIBCOMPAT@ -CVC4_COMPAT_LIBRARY_VERSION = @CVC4_COMPAT_LIBRARY_VERSION@ -CVC4_HAS_THREADS = @CVC4_HAS_THREADS@ -CVC4_LANGUAGE_BINDINGS = @CVC4_LANGUAGE_BINDINGS@ -CVC4_LIBRARY_VERSION = @CVC4_LIBRARY_VERSION@ -CVC4_PARSER_LIBRARY_VERSION = @CVC4_PARSER_LIBRARY_VERSION@ -CVC4_TLS = @CVC4_TLS@ -CVC4_TLS_SUPPORTED = @CVC4_TLS_SUPPORTED@ -CVC4_USE_CLN_IMP = @CVC4_USE_CLN_IMP@ -CVC4_USE_GMP_IMP = @CVC4_USE_GMP_IMP@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ -CXXTEST = @CXXTEST@ -CXXTESTGEN = @CXXTESTGEN@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ -DOXYGEN_EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@ -DOXYGEN_EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@ -DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ -DX_CONFIG = @DX_CONFIG@ -DX_DOCDIR = @DX_DOCDIR@ -DX_DOT = @DX_DOT@ -DX_DOXYGEN = @DX_DOXYGEN@ -DX_DVIPS = @DX_DVIPS@ -DX_EGREP = @DX_EGREP@ -DX_ENV = @DX_ENV@ -DX_FLAG_DX_CURRENT_FEATURE = @DX_FLAG_DX_CURRENT_FEATURE@ -DX_FLAG_chi = @DX_FLAG_chi@ -DX_FLAG_chm = @DX_FLAG_chm@ -DX_FLAG_doc = @DX_FLAG_doc@ -DX_FLAG_dot = @DX_FLAG_dot@ -DX_FLAG_html = @DX_FLAG_html@ -DX_FLAG_man = @DX_FLAG_man@ -DX_FLAG_pdf = @DX_FLAG_pdf@ -DX_FLAG_ps = @DX_FLAG_ps@ -DX_FLAG_rtf = @DX_FLAG_rtf@ -DX_FLAG_xml = @DX_FLAG_xml@ -DX_HHC = @DX_HHC@ -DX_LATEX = @DX_LATEX@ -DX_MAKEINDEX = @DX_MAKEINDEX@ -DX_PDFLATEX = @DX_PDFLATEX@ -DX_PERL = @DX_PERL@ -DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ -FLAG_VISIBILITY_HIDDEN = @FLAG_VISIBILITY_HIDDEN@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JAR = @JAR@ -JAVA = @JAVA@ -JAVAC = @JAVAC@ -JAVAH = @JAVAH@ -JAVA_CPPFLAGS = @JAVA_CPPFLAGS@ LD = @LD@ LDFLAGS = @LDFLAGS@ -LFSC = @LFSC@ -LFSCARGS = @LFSCARGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ -MAN_DATE = @MAN_DATE@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OCAMLC = @OCAMLC@ -OCAMLFIND = @OCAMLFIND@ -OCAMLMKTOP = @OCAMLMKTOP@ +OPENMP_CXXFLAGS = @OPENMP_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -241,33 +161,12 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PERL = @PERL@ -PERL_CPPFLAGS = @PERL_CPPFLAGS@ -PHP_CPPFLAGS = @PHP_CPPFLAGS@ -PKG_CONFIG = @PKG_CONFIG@ -PYTHON = @PYTHON@ -PYTHON_CONFIG = @PYTHON_CONFIG@ -PYTHON_CXXFLAGS = @PYTHON_CXXFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDE = @PYTHON_INCLUDE@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ -RUBY_CPPFLAGS = @RUBY_CPPFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_BINARY = @STATIC_BINARY@ STRIP = @STRIP@ -SWIG = @SWIG@ -TCL_CPPFLAGS = @TCL_CPPFLAGS@ -TEST_CPPFLAGS = @TEST_CPPFLAGS@ -TEST_CXXFLAGS = @TEST_CXXFLAGS@ -TEST_LDFLAGS = @TEST_LDFLAGS@ VERSION = @VERSION@ -WNO_CONVERSION_NULL = @WNO_CONVERSION_NULL@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -307,26 +206,17 @@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ -mk_include = @mk_include@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ -target = @target@ target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @@ -339,46 +229,71 @@ SUBDIRS = Solver mtl MTRand man EXTRA_DIST = HOWTO_VisualCpp HOWTO_MinGW32 \ LICENSE-GPL LICENSE-MIT TODO -all: all-recursive +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/prop/cryptominisat/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/prop/cryptominisat/Makefile + $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + $(SHELL) ./config.status --recheck -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs +distclean-libtool: + -rm -f libtool config.lt + # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, @@ -459,7 +374,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) mkid -fID $$unique tags: TAGS -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ @@ -476,7 +391,7 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ @@ -494,9 +409,9 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ fi; \ fi ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ @@ -515,6 +430,8 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -572,9 +489,124 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 check-am: all-am check: check-recursive -all-am: Makefile all-local +all-am: Makefile config.h all-local installdirs: installdirs-recursive installdirs-am: install: install-recursive @@ -607,8 +639,10 @@ clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags dvi: dvi-recursive @@ -651,6 +685,8 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -668,22 +704,25 @@ ps-am: uninstall-am: -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ - install-am install-strip tags-recursive +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am all-local check check-am clean clean-generic \ - clean-libtool ctags ctags-recursive distclean \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-recursive uninstall uninstall-am + all all-am all-local am--refresh check check-am clean \ + clean-generic clean-libtool ctags ctags-recursive dist \ + dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am all-local: Solver diff --git a/src/prop/cryptominisat/Solver/Makefile.in b/src/prop/cryptominisat/Solver/Makefile.in index 02344edd7..dd524fba2 100644 --- a/src/prop/cryptominisat/Solver/Makefile.in +++ b/src/prop/cryptominisat/Solver/Makefile.in @@ -36,29 +36,16 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -target_triplet = @target@ bin_PROGRAMS = cryptominisat$(EXEEXT) -subdir = src/prop/cryptominisat/Solver +subdir = Solver DIST_COMMON = $(pkgincludesub_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/antlr.m4 \ - $(top_srcdir)/config/ax_prog_doxygen.m4 \ - $(top_srcdir)/config/ax_tls.m4 \ - $(top_srcdir)/config/bindings.m4 $(top_srcdir)/config/boost.m4 \ - $(top_srcdir)/config/cudd.m4 $(top_srcdir)/config/cvc4.m4 \ - $(top_srcdir)/config/gcc_version.m4 \ - $(top_srcdir)/config/libtool.m4 \ - $(top_srcdir)/config/ltoptions.m4 \ - $(top_srcdir)/config/ltsugar.m4 \ - $(top_srcdir)/config/ltversion.m4 \ - $(top_srcdir)/config/lt~obsolete.m4 \ - $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/readline.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/cvc4autoconfig.h +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -94,47 +81,29 @@ am_libcryptominisat_la_OBJECTS = ClauseCleaner.lo FailedLitSearcher.lo \ ClauseVivifier.lo CompleteDetachReattacher.lo DimacsParser.lo \ OnlyNonLearntBins.lo SolverConf.lo DataSync.lo BothCache.lo libcryptominisat_la_OBJECTS = $(am_libcryptominisat_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) -am__v_lt_0 = --silent -libcryptominisat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ - $(AM_CXXFLAGS) $(CXXFLAGS) $(libcryptominisat_la_LDFLAGS) \ - $(LDFLAGS) -o $@ +libcryptominisat_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(libcryptominisat_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) am_cryptominisat_OBJECTS = Main.$(OBJEXT) cryptominisat_OBJECTS = $(am_cryptominisat_OBJECTS) cryptominisat_DEPENDENCIES = libcryptominisat.la -cryptominisat_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ - $(AM_CXXFLAGS) $(CXXFLAGS) $(cryptominisat_LDFLAGS) $(LDFLAGS) \ - -o $@ +cryptominisat_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(cryptominisat_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/config/depcomp +depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_$(V)) -am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) -am__v_CXX_0 = @echo " CXX " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -am__v_at_0 = @ +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_$(V)) -am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) -am__v_CXXLD_0 = @echo " CXXLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ SOURCES = $(libcryptominisat_la_SOURCES) $(cryptominisat_SOURCES) DIST_SOURCES = $(libcryptominisat_la_SOURCES) $(cryptominisat_SOURCES) HEADERS = $(pkgincludesub_HEADERS) @@ -143,128 +112,54 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -ANTLR = @ANTLR@ -ANTLR_HOME = @ANTLR_HOME@ -ANTLR_INCLUDES = @ANTLR_INCLUDES@ -ANTLR_LDFLAGS = @ANTLR_LDFLAGS@ AR = @AR@ -AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDPATH = @BOOST_LDPATH@ -BOOST_ROOT = @BOOST_ROOT@ -BOOST_THREAD_LDFLAGS = @BOOST_THREAD_LDFLAGS@ -BOOST_THREAD_LDPATH = @BOOST_THREAD_LDPATH@ -BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ -BUILDING_SHARED = @BUILDING_SHARED@ -BUILDING_STATIC = @BUILDING_STATIC@ -CAMLP4O = @CAMLP4O@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CLN_CFLAGS = @CLN_CFLAGS@ -CLN_LIBS = @CLN_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CSHARP_CPPFLAGS = @CSHARP_CPPFLAGS@ -CUDD_CPPFLAGS = @CUDD_CPPFLAGS@ -CUDD_LDFLAGS = @CUDD_LDFLAGS@ -CUDD_LIBS = @CUDD_LIBS@ -CVC4_BINDINGS_LIBRARY_VERSION = @CVC4_BINDINGS_LIBRARY_VERSION@ -CVC4_BUILD_LIBCOMPAT = @CVC4_BUILD_LIBCOMPAT@ -CVC4_COMPAT_LIBRARY_VERSION = @CVC4_COMPAT_LIBRARY_VERSION@ -CVC4_HAS_THREADS = @CVC4_HAS_THREADS@ -CVC4_LANGUAGE_BINDINGS = @CVC4_LANGUAGE_BINDINGS@ -CVC4_LIBRARY_VERSION = @CVC4_LIBRARY_VERSION@ -CVC4_PARSER_LIBRARY_VERSION = @CVC4_PARSER_LIBRARY_VERSION@ -CVC4_TLS = @CVC4_TLS@ -CVC4_TLS_SUPPORTED = @CVC4_TLS_SUPPORTED@ -CVC4_USE_CLN_IMP = @CVC4_USE_CLN_IMP@ -CVC4_USE_GMP_IMP = @CVC4_USE_GMP_IMP@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ -CXXTEST = @CXXTEST@ -CXXTESTGEN = @CXXTESTGEN@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ -DOXYGEN_EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@ -DOXYGEN_EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@ -DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ -DX_CONFIG = @DX_CONFIG@ -DX_DOCDIR = @DX_DOCDIR@ -DX_DOT = @DX_DOT@ -DX_DOXYGEN = @DX_DOXYGEN@ -DX_DVIPS = @DX_DVIPS@ -DX_EGREP = @DX_EGREP@ -DX_ENV = @DX_ENV@ -DX_FLAG_DX_CURRENT_FEATURE = @DX_FLAG_DX_CURRENT_FEATURE@ -DX_FLAG_chi = @DX_FLAG_chi@ -DX_FLAG_chm = @DX_FLAG_chm@ -DX_FLAG_doc = @DX_FLAG_doc@ -DX_FLAG_dot = @DX_FLAG_dot@ -DX_FLAG_html = @DX_FLAG_html@ -DX_FLAG_man = @DX_FLAG_man@ -DX_FLAG_pdf = @DX_FLAG_pdf@ -DX_FLAG_ps = @DX_FLAG_ps@ -DX_FLAG_rtf = @DX_FLAG_rtf@ -DX_FLAG_xml = @DX_FLAG_xml@ -DX_HHC = @DX_HHC@ -DX_LATEX = @DX_LATEX@ -DX_MAKEINDEX = @DX_MAKEINDEX@ -DX_PDFLATEX = @DX_PDFLATEX@ -DX_PERL = @DX_PERL@ -DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ -FLAG_VISIBILITY_HIDDEN = @FLAG_VISIBILITY_HIDDEN@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JAR = @JAR@ -JAVA = @JAVA@ -JAVAC = @JAVAC@ -JAVAH = @JAVAH@ -JAVA_CPPFLAGS = @JAVA_CPPFLAGS@ LD = @LD@ LDFLAGS = @LDFLAGS@ -LFSC = @LFSC@ -LFSCARGS = @LFSCARGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ -MAN_DATE = @MAN_DATE@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OCAMLC = @OCAMLC@ -OCAMLFIND = @OCAMLFIND@ -OCAMLMKTOP = @OCAMLMKTOP@ +OPENMP_CXXFLAGS = @OPENMP_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -275,33 +170,12 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PERL = @PERL@ -PERL_CPPFLAGS = @PERL_CPPFLAGS@ -PHP_CPPFLAGS = @PHP_CPPFLAGS@ -PKG_CONFIG = @PKG_CONFIG@ -PYTHON = @PYTHON@ -PYTHON_CONFIG = @PYTHON_CONFIG@ -PYTHON_CXXFLAGS = @PYTHON_CXXFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDE = @PYTHON_INCLUDE@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ -RUBY_CPPFLAGS = @RUBY_CPPFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_BINARY = @STATIC_BINARY@ STRIP = @STRIP@ -SWIG = @SWIG@ -TCL_CPPFLAGS = @TCL_CPPFLAGS@ -TEST_CPPFLAGS = @TEST_CPPFLAGS@ -TEST_CXXFLAGS = @TEST_CXXFLAGS@ -TEST_LDFLAGS = @TEST_LDFLAGS@ VERSION = @VERSION@ -WNO_CONVERSION_NULL = @WNO_CONVERSION_NULL@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -341,26 +215,17 @@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ -mk_include = @mk_include@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ -target = @target@ target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @@ -398,7 +263,7 @@ all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -407,9 +272,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/prop/cryptominisat/Solver/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Solver/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/prop/cryptominisat/Solver/Makefile + $(AUTOMAKE) --gnu Solver/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -423,9 +288,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) +$(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @@ -460,7 +325,7 @@ clean-libLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libcryptominisat.la: $(libcryptominisat_la_OBJECTS) $(libcryptominisat_la_DEPENDENCIES) - $(AM_V_CXXLD)$(libcryptominisat_la_LINK) -rpath $(libdir) $(libcryptominisat_la_OBJECTS) $(libcryptominisat_la_LIBADD) $(LIBS) + $(libcryptominisat_la_LINK) -rpath $(libdir) $(libcryptominisat_la_OBJECTS) $(libcryptominisat_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @@ -506,7 +371,7 @@ clean-binPROGRAMS: rm -f $$list cryptominisat$(EXEEXT): $(cryptominisat_OBJECTS) $(cryptominisat_DEPENDENCIES) @rm -f cryptominisat$(EXEEXT) - $(AM_V_CXXLD)$(cryptominisat_LINK) $(cryptominisat_OBJECTS) $(cryptominisat_LDADD) $(LIBS) + $(cryptominisat_LINK) $(cryptominisat_OBJECTS) $(cryptominisat_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -541,25 +406,22 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XorSubsumer.Plo@am__quote@ .cpp.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< diff --git a/src/prop/cryptominisat/man/Makefile.in b/src/prop/cryptominisat/man/Makefile.in index 7dc705cf1..5542511eb 100644 --- a/src/prop/cryptominisat/man/Makefile.in +++ b/src/prop/cryptominisat/man/Makefile.in @@ -33,35 +33,16 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -target_triplet = @target@ -subdir = src/prop/cryptominisat/man +subdir = man DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/antlr.m4 \ - $(top_srcdir)/config/ax_prog_doxygen.m4 \ - $(top_srcdir)/config/ax_tls.m4 \ - $(top_srcdir)/config/bindings.m4 $(top_srcdir)/config/boost.m4 \ - $(top_srcdir)/config/cudd.m4 $(top_srcdir)/config/cvc4.m4 \ - $(top_srcdir)/config/gcc_version.m4 \ - $(top_srcdir)/config/libtool.m4 \ - $(top_srcdir)/config/ltoptions.m4 \ - $(top_srcdir)/config/ltsugar.m4 \ - $(top_srcdir)/config/ltversion.m4 \ - $(top_srcdir)/config/lt~obsolete.m4 \ - $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/readline.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/cvc4autoconfig.h +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -am__v_at_0 = @ SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -92,128 +73,54 @@ MANS = $(man_MANS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -ANTLR = @ANTLR@ -ANTLR_HOME = @ANTLR_HOME@ -ANTLR_INCLUDES = @ANTLR_INCLUDES@ -ANTLR_LDFLAGS = @ANTLR_LDFLAGS@ AR = @AR@ -AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDPATH = @BOOST_LDPATH@ -BOOST_ROOT = @BOOST_ROOT@ -BOOST_THREAD_LDFLAGS = @BOOST_THREAD_LDFLAGS@ -BOOST_THREAD_LDPATH = @BOOST_THREAD_LDPATH@ -BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ -BUILDING_SHARED = @BUILDING_SHARED@ -BUILDING_STATIC = @BUILDING_STATIC@ -CAMLP4O = @CAMLP4O@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CLN_CFLAGS = @CLN_CFLAGS@ -CLN_LIBS = @CLN_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CSHARP_CPPFLAGS = @CSHARP_CPPFLAGS@ -CUDD_CPPFLAGS = @CUDD_CPPFLAGS@ -CUDD_LDFLAGS = @CUDD_LDFLAGS@ -CUDD_LIBS = @CUDD_LIBS@ -CVC4_BINDINGS_LIBRARY_VERSION = @CVC4_BINDINGS_LIBRARY_VERSION@ -CVC4_BUILD_LIBCOMPAT = @CVC4_BUILD_LIBCOMPAT@ -CVC4_COMPAT_LIBRARY_VERSION = @CVC4_COMPAT_LIBRARY_VERSION@ -CVC4_HAS_THREADS = @CVC4_HAS_THREADS@ -CVC4_LANGUAGE_BINDINGS = @CVC4_LANGUAGE_BINDINGS@ -CVC4_LIBRARY_VERSION = @CVC4_LIBRARY_VERSION@ -CVC4_PARSER_LIBRARY_VERSION = @CVC4_PARSER_LIBRARY_VERSION@ -CVC4_TLS = @CVC4_TLS@ -CVC4_TLS_SUPPORTED = @CVC4_TLS_SUPPORTED@ -CVC4_USE_CLN_IMP = @CVC4_USE_CLN_IMP@ -CVC4_USE_GMP_IMP = @CVC4_USE_GMP_IMP@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ -CXXTEST = @CXXTEST@ -CXXTESTGEN = @CXXTESTGEN@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ -DOXYGEN_EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@ -DOXYGEN_EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@ -DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ -DX_CONFIG = @DX_CONFIG@ -DX_DOCDIR = @DX_DOCDIR@ -DX_DOT = @DX_DOT@ -DX_DOXYGEN = @DX_DOXYGEN@ -DX_DVIPS = @DX_DVIPS@ -DX_EGREP = @DX_EGREP@ -DX_ENV = @DX_ENV@ -DX_FLAG_DX_CURRENT_FEATURE = @DX_FLAG_DX_CURRENT_FEATURE@ -DX_FLAG_chi = @DX_FLAG_chi@ -DX_FLAG_chm = @DX_FLAG_chm@ -DX_FLAG_doc = @DX_FLAG_doc@ -DX_FLAG_dot = @DX_FLAG_dot@ -DX_FLAG_html = @DX_FLAG_html@ -DX_FLAG_man = @DX_FLAG_man@ -DX_FLAG_pdf = @DX_FLAG_pdf@ -DX_FLAG_ps = @DX_FLAG_ps@ -DX_FLAG_rtf = @DX_FLAG_rtf@ -DX_FLAG_xml = @DX_FLAG_xml@ -DX_HHC = @DX_HHC@ -DX_LATEX = @DX_LATEX@ -DX_MAKEINDEX = @DX_MAKEINDEX@ -DX_PDFLATEX = @DX_PDFLATEX@ -DX_PERL = @DX_PERL@ -DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ -FLAG_VISIBILITY_HIDDEN = @FLAG_VISIBILITY_HIDDEN@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JAR = @JAR@ -JAVA = @JAVA@ -JAVAC = @JAVAC@ -JAVAH = @JAVAH@ -JAVA_CPPFLAGS = @JAVA_CPPFLAGS@ LD = @LD@ LDFLAGS = @LDFLAGS@ -LFSC = @LFSC@ -LFSCARGS = @LFSCARGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ -MAN_DATE = @MAN_DATE@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OCAMLC = @OCAMLC@ -OCAMLFIND = @OCAMLFIND@ -OCAMLMKTOP = @OCAMLMKTOP@ +OPENMP_CXXFLAGS = @OPENMP_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -224,33 +131,12 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PERL = @PERL@ -PERL_CPPFLAGS = @PERL_CPPFLAGS@ -PHP_CPPFLAGS = @PHP_CPPFLAGS@ -PKG_CONFIG = @PKG_CONFIG@ -PYTHON = @PYTHON@ -PYTHON_CONFIG = @PYTHON_CONFIG@ -PYTHON_CXXFLAGS = @PYTHON_CXXFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDE = @PYTHON_INCLUDE@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ -RUBY_CPPFLAGS = @RUBY_CPPFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_BINARY = @STATIC_BINARY@ STRIP = @STRIP@ -SWIG = @SWIG@ -TCL_CPPFLAGS = @TCL_CPPFLAGS@ -TEST_CPPFLAGS = @TEST_CPPFLAGS@ -TEST_CXXFLAGS = @TEST_CXXFLAGS@ -TEST_LDFLAGS = @TEST_LDFLAGS@ VERSION = @VERSION@ -WNO_CONVERSION_NULL = @WNO_CONVERSION_NULL@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -290,26 +176,17 @@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ -mk_include = @mk_include@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ -target = @target@ target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @@ -318,7 +195,7 @@ EXTRA_DIST = $(man_MANS) all: all-am .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -327,9 +204,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/prop/cryptominisat/man/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/prop/cryptominisat/man/Makefile + $(AUTOMAKE) --gnu man/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -343,9 +220,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) +$(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): diff --git a/src/prop/cryptominisat/mtl/Makefile.in b/src/prop/cryptominisat/mtl/Makefile.in index 7d8c8ce1b..eb9b73e19 100644 --- a/src/prop/cryptominisat/mtl/Makefile.in +++ b/src/prop/cryptominisat/mtl/Makefile.in @@ -34,36 +34,17 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -target_triplet = @target@ -subdir = src/prop/cryptominisat/mtl +subdir = mtl DIST_COMMON = $(pkgincludesub_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/antlr.m4 \ - $(top_srcdir)/config/ax_prog_doxygen.m4 \ - $(top_srcdir)/config/ax_tls.m4 \ - $(top_srcdir)/config/bindings.m4 $(top_srcdir)/config/boost.m4 \ - $(top_srcdir)/config/cudd.m4 $(top_srcdir)/config/cvc4.m4 \ - $(top_srcdir)/config/gcc_version.m4 \ - $(top_srcdir)/config/libtool.m4 \ - $(top_srcdir)/config/ltoptions.m4 \ - $(top_srcdir)/config/ltsugar.m4 \ - $(top_srcdir)/config/ltversion.m4 \ - $(top_srcdir)/config/lt~obsolete.m4 \ - $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/readline.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/cvc4autoconfig.h +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -am__v_at_0 = @ SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -94,128 +75,54 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -ANTLR = @ANTLR@ -ANTLR_HOME = @ANTLR_HOME@ -ANTLR_INCLUDES = @ANTLR_INCLUDES@ -ANTLR_LDFLAGS = @ANTLR_LDFLAGS@ AR = @AR@ -AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDPATH = @BOOST_LDPATH@ -BOOST_ROOT = @BOOST_ROOT@ -BOOST_THREAD_LDFLAGS = @BOOST_THREAD_LDFLAGS@ -BOOST_THREAD_LDPATH = @BOOST_THREAD_LDPATH@ -BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ -BUILDING_SHARED = @BUILDING_SHARED@ -BUILDING_STATIC = @BUILDING_STATIC@ -CAMLP4O = @CAMLP4O@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CLN_CFLAGS = @CLN_CFLAGS@ -CLN_LIBS = @CLN_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CSHARP_CPPFLAGS = @CSHARP_CPPFLAGS@ -CUDD_CPPFLAGS = @CUDD_CPPFLAGS@ -CUDD_LDFLAGS = @CUDD_LDFLAGS@ -CUDD_LIBS = @CUDD_LIBS@ -CVC4_BINDINGS_LIBRARY_VERSION = @CVC4_BINDINGS_LIBRARY_VERSION@ -CVC4_BUILD_LIBCOMPAT = @CVC4_BUILD_LIBCOMPAT@ -CVC4_COMPAT_LIBRARY_VERSION = @CVC4_COMPAT_LIBRARY_VERSION@ -CVC4_HAS_THREADS = @CVC4_HAS_THREADS@ -CVC4_LANGUAGE_BINDINGS = @CVC4_LANGUAGE_BINDINGS@ -CVC4_LIBRARY_VERSION = @CVC4_LIBRARY_VERSION@ -CVC4_PARSER_LIBRARY_VERSION = @CVC4_PARSER_LIBRARY_VERSION@ -CVC4_TLS = @CVC4_TLS@ -CVC4_TLS_SUPPORTED = @CVC4_TLS_SUPPORTED@ -CVC4_USE_CLN_IMP = @CVC4_USE_CLN_IMP@ -CVC4_USE_GMP_IMP = @CVC4_USE_GMP_IMP@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ -CXXTEST = @CXXTEST@ -CXXTESTGEN = @CXXTESTGEN@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ -DOXYGEN_EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@ -DOXYGEN_EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@ -DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ -DX_CONFIG = @DX_CONFIG@ -DX_DOCDIR = @DX_DOCDIR@ -DX_DOT = @DX_DOT@ -DX_DOXYGEN = @DX_DOXYGEN@ -DX_DVIPS = @DX_DVIPS@ -DX_EGREP = @DX_EGREP@ -DX_ENV = @DX_ENV@ -DX_FLAG_DX_CURRENT_FEATURE = @DX_FLAG_DX_CURRENT_FEATURE@ -DX_FLAG_chi = @DX_FLAG_chi@ -DX_FLAG_chm = @DX_FLAG_chm@ -DX_FLAG_doc = @DX_FLAG_doc@ -DX_FLAG_dot = @DX_FLAG_dot@ -DX_FLAG_html = @DX_FLAG_html@ -DX_FLAG_man = @DX_FLAG_man@ -DX_FLAG_pdf = @DX_FLAG_pdf@ -DX_FLAG_ps = @DX_FLAG_ps@ -DX_FLAG_rtf = @DX_FLAG_rtf@ -DX_FLAG_xml = @DX_FLAG_xml@ -DX_HHC = @DX_HHC@ -DX_LATEX = @DX_LATEX@ -DX_MAKEINDEX = @DX_MAKEINDEX@ -DX_PDFLATEX = @DX_PDFLATEX@ -DX_PERL = @DX_PERL@ -DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ -FLAG_VISIBILITY_HIDDEN = @FLAG_VISIBILITY_HIDDEN@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JAR = @JAR@ -JAVA = @JAVA@ -JAVAC = @JAVAC@ -JAVAH = @JAVAH@ -JAVA_CPPFLAGS = @JAVA_CPPFLAGS@ LD = @LD@ LDFLAGS = @LDFLAGS@ -LFSC = @LFSC@ -LFSCARGS = @LFSCARGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ -MAN_DATE = @MAN_DATE@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OCAMLC = @OCAMLC@ -OCAMLFIND = @OCAMLFIND@ -OCAMLMKTOP = @OCAMLMKTOP@ +OPENMP_CXXFLAGS = @OPENMP_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -226,33 +133,12 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PERL = @PERL@ -PERL_CPPFLAGS = @PERL_CPPFLAGS@ -PHP_CPPFLAGS = @PHP_CPPFLAGS@ -PKG_CONFIG = @PKG_CONFIG@ -PYTHON = @PYTHON@ -PYTHON_CONFIG = @PYTHON_CONFIG@ -PYTHON_CXXFLAGS = @PYTHON_CXXFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDE = @PYTHON_INCLUDE@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ -RUBY_CPPFLAGS = @RUBY_CPPFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_BINARY = @STATIC_BINARY@ STRIP = @STRIP@ -SWIG = @SWIG@ -TCL_CPPFLAGS = @TCL_CPPFLAGS@ -TEST_CPPFLAGS = @TEST_CPPFLAGS@ -TEST_CXXFLAGS = @TEST_CXXFLAGS@ -TEST_LDFLAGS = @TEST_LDFLAGS@ VERSION = @VERSION@ -WNO_CONVERSION_NULL = @WNO_CONVERSION_NULL@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -292,26 +178,17 @@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ -mk_include = @mk_include@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ -target = @target@ target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @@ -320,7 +197,7 @@ pkgincludesub_HEADERS = Alg.h Heap.h Vec.h all: all-am .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -329,9 +206,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/prop/cryptominisat/mtl/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mtl/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/prop/cryptominisat/mtl/Makefile + $(AUTOMAKE) --gnu mtl/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -345,9 +222,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) +$(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp index e73af60e9..97407a425 100644 --- a/src/smt/smt_engine.cpp +++ b/src/smt/smt_engine.cpp @@ -291,6 +291,9 @@ SmtEngine::SmtEngine(ExprManager* em) throw(AssertionException) : setTimeLimit(Options::current()->cumulativeMillisecondLimit, true); } + + d_propEngine->assertFormula(NodeManager::currentNM()->mkConst<bool>(true)); + d_propEngine->assertFormula(NodeManager::currentNM()->mkConst<bool>(false).notNode()); } void SmtEngine::shutdown() { diff --git a/src/theory/arith/Makefile.am b/src/theory/arith/Makefile.am index 4cff4a782..b97a6f384 100644 --- a/src/theory/arith/Makefile.am +++ b/src/theory/arith/Makefile.am @@ -12,11 +12,10 @@ libarith_la_SOURCES = \ arith_rewriter.cpp \ arith_static_learner.h \ arith_static_learner.cpp \ - arith_prop_manager.h \ - arith_prop_manager.cpp \ arithvar_node_map.h \ - atom_database.h \ - atom_database.cpp \ + constraint_forward.h \ + constraint.h \ + constraint.cpp \ difference_manager.h \ difference_manager.cpp \ normal_form.h\ @@ -28,7 +27,6 @@ libarith_la_SOURCES = \ partial_model.cpp \ linear_equality.h \ linear_equality.cpp \ - ordered_set.h \ arithvar_set.h \ tableau.h \ tableau.cpp \ diff --git a/src/theory/arith/arith_prop_manager.cpp b/src/theory/arith/arith_prop_manager.cpp deleted file mode 100644 index dc9b0ddb9..000000000 --- a/src/theory/arith/arith_prop_manager.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/********************* */ -/*! \file arith_prop_manager.cpp - ** \verbatim - ** Original author: taking - ** Major contributors: none - ** Minor contributors (to current version): none - ** This file is part of the CVC4 prototype. - ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) - ** Courant Institute of Mathematical Sciences - ** New York University - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim - ** - ** \brief [[ Add one-line brief description here ]] - ** - ** [[ Add lengthier description here ]] - ** \todo document this file - **/ - - -#include "theory/arith/arith_prop_manager.h" - -#include "theory/arith/arith_utilities.h" -#include "context/context.h" -#include "context/cdlist.h" -#include "context/cdhashmap.h" -#include "context/cdo.h" - -using namespace CVC4::kind; -using namespace std; - - -namespace CVC4 { -namespace theory { -namespace arith { - -bool ArithPropManager::isAsserted(TNode n) const{ - Node satValue = d_valuation.getSatValue(n); - if(satValue.isNull()){ - return false; - }else{ - //Assert(satValue.getConst<bool>()); - return true; - } -} - - -Node ArithPropManager::strictlyWeakerAssertedUpperBound(ArithVar v, const DeltaRational& b) const{ - Node bound = boundAsNode(true, v, b); - - Assert(b.getInfinitesimalPart() <= 0); - bool largeEpsilon = (b.getInfinitesimalPart() < -1); - - Node weaker = bound; - do { - if(largeEpsilon){ - weaker = d_atomDatabase.getBestImpliedUpperBound(weaker); - largeEpsilon = false; - }else{ - weaker = d_atomDatabase.getWeakerImpliedUpperBound(weaker); - } - }while(!weaker.isNull() && !isAsserted(weaker)); - return weaker; -} - -Node ArithPropManager::strictlyWeakerAssertedLowerBound(ArithVar v, const DeltaRational& b) const{ - Debug("ArithPropManager") << "strictlyWeakerAssertedLowerBound" << endl; - Node bound = boundAsNode(false, v, b); - - Assert(b.getInfinitesimalPart() >= 0); - bool largeEpsilon = (b.getInfinitesimalPart() > 1); - - Node weaker = bound; - Debug("ArithPropManager") << bound << b << endl; - do { - if(largeEpsilon){ - weaker = d_atomDatabase.getBestImpliedLowerBound(weaker); - largeEpsilon = false; - }else{ - weaker = d_atomDatabase.getWeakerImpliedLowerBound(weaker); - } - }while(!weaker.isNull() && !isAsserted(weaker)); - Debug("ArithPropManager") << "res: " << weaker << endl; - return weaker; -} - -Node ArithPropManager::getBestImpliedLowerBound(ArithVar v, const DeltaRational& b) const{ - Node bound = boundAsNode(false, v, b); - return d_atomDatabase.getBestImpliedLowerBound(bound); -} -Node ArithPropManager::getBestImpliedUpperBound(ArithVar v, const DeltaRational& b) const{ - Node bound = boundAsNode(true, v, b); - return d_atomDatabase.getBestImpliedUpperBound(bound); -} - -Node ArithPropManager::boundAsNode(bool upperbound, ArithVar var, const DeltaRational& b) const { - Assert((!upperbound) || (b.getInfinitesimalPart() <= 0) ); - Assert(upperbound || (b.getInfinitesimalPart() >= 0) ); - - Node varAsNode = d_arithvarNodeMap.asNode(var); - Kind kind; - bool negate; - if(upperbound){ - negate = b.getInfinitesimalPart() < 0; - kind = negate ? GEQ : LEQ; - } else{ - negate = b.getInfinitesimalPart() > 0; - kind = negate ? LEQ : GEQ; - } - - Node righthand = mkRationalNode(b.getNoninfinitesimalPart()); - Node bAsNode = NodeBuilder<2>(kind) << varAsNode << righthand; - - if(negate){ - bAsNode = NodeBuilder<1>(NOT) << bAsNode; - } - - return bAsNode; -} - -bool ArithPropManager::propagateArithVar(bool upperbound, ArithVar var, const DeltaRational& b, TNode reason){ - bool success = false; - - ++d_statistics.d_propagateArithVarCalls; - - Node bAsNode = boundAsNode(upperbound, var ,b); - - Node bestImplied = upperbound ? - d_atomDatabase.getBestImpliedUpperBound(bAsNode): - d_atomDatabase.getBestImpliedLowerBound(bAsNode); - - Debug("ArithPropManager") << upperbound <<","<< var <<","<< b <<","<< reason << endl - << bestImplied << endl; - - if(!bestImplied.isNull()){ - bool asserted = isAsserted(bestImplied); - - if( !asserted && !isPropagated(bestImplied)){ - propagate(bestImplied, reason, false); - ++d_statistics.d_addedPropagation; - success = true; - }else if(!asserted){ - ++d_statistics.d_alreadyPropagatedNode; - }else if(!isPropagated(bestImplied)){ - ++d_statistics.d_alreadySetSatLiteral; - } - } - return success; -} - -ArithPropManager::Statistics::Statistics(): - d_propagateArithVarCalls("arith::prop-manager::propagateArithVarCalls",0), - d_addedPropagation("arith::prop-manager::addedPropagation",0), - d_alreadySetSatLiteral("arith::prop-manager::alreadySetSatLiteral",0), - d_alreadyPropagatedNode("arith::prop-manager::alreadyPropagatedNode",0) -{ - StatisticsRegistry::registerStat(&d_propagateArithVarCalls); - StatisticsRegistry::registerStat(&d_alreadySetSatLiteral); - StatisticsRegistry::registerStat(&d_alreadyPropagatedNode); - StatisticsRegistry::registerStat(&d_addedPropagation); -} - -ArithPropManager::Statistics::~Statistics() -{ - StatisticsRegistry::unregisterStat(&d_propagateArithVarCalls); - StatisticsRegistry::unregisterStat(&d_alreadySetSatLiteral); - StatisticsRegistry::unregisterStat(&d_alreadyPropagatedNode); - StatisticsRegistry::unregisterStat(&d_addedPropagation); -} - -}; /* namesapce arith */ -}; /* namespace theory */ -}; /* namespace CVC4 */ diff --git a/src/theory/arith/arith_prop_manager.h b/src/theory/arith/arith_prop_manager.h deleted file mode 100644 index 900a0ed58..000000000 --- a/src/theory/arith/arith_prop_manager.h +++ /dev/null @@ -1,184 +0,0 @@ -/********************* */ -/*! \file arith_prop_manager.h - ** \verbatim - ** Original author: taking - ** Major contributors: none - ** Minor contributors (to current version): none - ** This file is part of the CVC4 prototype. - ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) - ** Courant Institute of Mathematical Sciences - ** New York University - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim - ** - ** \brief [[ Add one-line brief description here ]] - ** - ** [[ Add lengthier description here ]] - ** \todo document this file - **/ - -#include "cvc4_private.h" - -#ifndef __CVC4__THEORY__ARITH__ARITH_PROP_MANAGER_H -#define __CVC4__THEORY__ARITH__ARITH_PROP_MANAGER_H - -#include "theory/valuation.h" -#include "theory/arith/arithvar.h" -#include "theory/arith/arithvar_node_map.h" -#include "theory/arith/atom_database.h" -#include "theory/arith/delta_rational.h" -#include "context/context.h" -#include "context/cdlist.h" -#include "context/cdhashmap.h" -#include "context/cdo.h" -#include "theory/rewriter.h" -#include "util/stats.h" - -namespace CVC4 { -namespace theory { -namespace arith { - -class PropManager { -public: - struct PropUnit { - // consequent <= antecedent - // i.e. the antecedent is the explanation of the consequent. - Node consequent; - Node antecedent; - bool flag; - PropUnit(Node c, Node a, bool f) : - consequent(c), antecedent(a), flag(f) - {} - }; - -private: - context::CDList<PropUnit> d_propagated; - context::CDO<uint32_t> d_propagatedPos; - - /* This maps the node a theory engine will request on an explain call to - * to its corresponding PropUnit. - * This is node is potentially both the consequent or Rewriter::rewrite(consequent). - */ - typedef context::CDHashMap<Node, size_t, NodeHashFunction> ExplainMap; - ExplainMap d_explanationMap; - - size_t getIndex(TNode n) const { - Assert(isPropagated(n)); - return (*(d_explanationMap.find(n))).second; - } - -public: - - PropManager(context::Context* c): - d_propagated(c), - d_propagatedPos(c, 0), - d_explanationMap(c) - { } - - const PropUnit& getUnit(TNode n) const { - return d_propagated[getIndex(n)]; - } - - bool isPropagated(TNode n) const { - return d_explanationMap.find(n) != d_explanationMap.end(); - } - - bool isFlagged(TNode n) const { - return getUnit(n).flag; - } - - void propagate(TNode n, Node reason, bool flag) { - Assert(!isPropagated(n)); - - if(flag){ - Node rewritten = Rewriter::rewrite(n); - d_explanationMap.insert(rewritten, d_propagated.size()); - }else{ - //If !flag, then the rewriter is idempotent on n. - Assert(Rewriter::rewrite(n) == n); - } - d_explanationMap.insert(n, d_propagated.size()); - d_propagated.push_back(PropUnit(n, reason, flag)); - - Debug("ArithPropManager") << n << std::endl << "<="<< reason<< std::endl; - } - - bool hasMorePropagations() const { - return d_propagatedPos < d_propagated.size(); - } - - const PropUnit& getNextPropagation() { - Assert(hasMorePropagations()); - const PropUnit& prop = d_propagated[d_propagatedPos]; - d_propagatedPos = d_propagatedPos + 1; - return prop; - } - - TNode explain(TNode n) const { - return getUnit(n).antecedent; - } - -};/* class PropManager */ - -class ArithPropManager : public PropManager { -private: - const ArithVarNodeMap& d_arithvarNodeMap; - const ArithAtomDatabase& d_atomDatabase; - Valuation d_valuation; - -public: - ArithPropManager(context::Context* c, - const ArithVarNodeMap& map, - const ArithAtomDatabase& db, - Valuation v): - PropManager(c), d_arithvarNodeMap(map), d_atomDatabase(db), d_valuation(v) - {} - - /** - * Returns true if the node has a value in sat solver in the current context. - * In debug mode this fails an Assert() if the node has a negative assignment. - */ - bool isAsserted(TNode n) const; - - /** Returns true if a bound was added. */ - bool propagateArithVar(bool upperbound, ArithVar var, const DeltaRational& b, TNode reason); - - Node boundAsNode(bool upperbound, ArithVar var, const DeltaRational& b) const; - - Node strictlyWeakerLowerBound(TNode n) const{ - return d_atomDatabase.getWeakerImpliedLowerBound(n); - } - Node strictlyWeakerUpperBound(TNode n) const{ - return d_atomDatabase.getWeakerImpliedUpperBound(n); - } - - Node strictlyWeakerAssertedUpperBound(ArithVar v, const DeltaRational& b) const; - - Node strictlyWeakerAssertedLowerBound(ArithVar v, const DeltaRational& b) const; - - Node getBestImpliedLowerBound(ArithVar v, const DeltaRational& b) const; - Node getBestImpliedUpperBound(ArithVar v, const DeltaRational& b) const; - - bool containsLiteral(TNode n) const { - return d_atomDatabase.containsLiteral(n); - } - -private: - class Statistics { - public: - IntStat d_propagateArithVarCalls; - IntStat d_addedPropagation; - IntStat d_alreadySetSatLiteral; - IntStat d_alreadyPropagatedNode; - - Statistics(); - ~Statistics(); - }; - Statistics d_statistics; -}; - -}/* CVC4::theory::arith namespace */ -}/* CVC4::theory namespace */ -}/* CVC4 namespace */ - -#endif /* __CVC4__THEORY__ARITH__ARITH_PROP_MANAGER_H */ diff --git a/src/theory/arith/arith_rewriter.cpp b/src/theory/arith/arith_rewriter.cpp index 30568c3ca..863eb5c31 100644 --- a/src/theory/arith/arith_rewriter.cpp +++ b/src/theory/arith/arith_rewriter.cpp @@ -204,34 +204,30 @@ RewriteResponse ArithRewriter::postRewriteMult(TNode t){ return RewriteResponse(REWRITE_DONE, res.getNode()); } -RewriteResponse ArithRewriter::postRewriteAtomConstantRHS(TNode t){ - TNode left = t[0]; - TNode right = t[1]; +// RewriteResponse ArithRewriter::postRewriteAtomConstantRHS(TNode t){ +// TNode left = t[0]; +// TNode right = t[1]; - Comparison cmp = Comparison::mkNormalComparison(t.getKind(), Polynomial::parsePolynomial(left), Constant(right)); +// Polynomial pLeft = Polynomial::parsePolynomial(left); + - Assert(cmp.isNormalForm()); - return RewriteResponse(REWRITE_DONE, cmp.getNode()); -} +// Comparison cmp = Comparison::mkComparison(t.getKind(), Polynomial::parsePolynomial(left), Constant(right)); + +// Assert(cmp.isNormalForm()); +// return RewriteResponse(REWRITE_DONE, cmp.getNode()); +// } RewriteResponse ArithRewriter::postRewriteAtom(TNode atom){ // left |><| right TNode left = atom[0]; TNode right = atom[1]; - if(right.getMetaKind() == kind::metakind::CONSTANT){ - return postRewriteAtomConstantRHS(atom); - }else{ - Polynomial pleft = Polynomial::parsePolynomial(left); - Polynomial pright = Polynomial::parsePolynomial(right); - - Polynomial diff = pleft - pright; - - Constant cZero = Constant::mkConstant(Rational(0)); - Node reduction = NodeManager::currentNM()->mkNode(atom.getKind(), diff.getNode(), cZero.getNode()); + Polynomial pleft = Polynomial::parsePolynomial(left); + Polynomial pright = Polynomial::parsePolynomial(right); - return postRewriteAtomConstantRHS(reduction); - } + Comparison cmp = Comparison::mkComparison(atom.getKind(), pleft, pright); + Assert(cmp.isNormalForm()); + return RewriteResponse(REWRITE_DONE, cmp.getNode()); } RewriteResponse ArithRewriter::preRewriteAtom(TNode atom){ diff --git a/src/theory/arith/arith_rewriter.h b/src/theory/arith/arith_rewriter.h index 07c009b2e..748ed8686 100644 --- a/src/theory/arith/arith_rewriter.h +++ b/src/theory/arith/arith_rewriter.h @@ -66,7 +66,6 @@ private: static RewriteResponse preRewriteAtom(TNode t); static RewriteResponse postRewriteAtom(TNode t); - static RewriteResponse postRewriteAtomConstantRHS(TNode t); static bool isAtom(TNode n); diff --git a/src/theory/arith/arith_static_learner.cpp b/src/theory/arith/arith_static_learner.cpp index 2f4f6e32b..8ecc3abdc 100644 --- a/src/theory/arith/arith_static_learner.cpp +++ b/src/theory/arith/arith_static_learner.cpp @@ -261,7 +261,7 @@ void ArithStaticLearner::iteMinMax(TNode n, NodeBuilder<>& learned){ Assert(isRelationOperator(n[0].getKind())); TNode c = n[0]; - Kind k = simplifiedKind(c); + Kind k = oldSimplifiedKind(c); TNode t = n[1]; TNode e = n[2]; TNode cleft = (c.getKind() == NOT) ? c[0][0] : c[0]; diff --git a/src/theory/arith/arith_utilities.h b/src/theory/arith/arith_utilities.h index a5d94ec40..af32c3f87 100644 --- a/src/theory/arith/arith_utilities.h +++ b/src/theory/arith/arith_utilities.h @@ -168,17 +168,17 @@ inline int deltaCoeff(Kind k){ * - (NOT (GT left right)) -> LEQ * If none of these match, it returns UNDEFINED_KIND. */ - inline Kind simplifiedKind(TNode assertion){ - switch(assertion.getKind()){ + inline Kind oldSimplifiedKind(TNode literal){ + switch(literal.getKind()){ case kind::LT: case kind::GT: case kind::LEQ: case kind::GEQ: case kind::EQUAL: - return assertion.getKind(); + return literal.getKind(); case kind::NOT: { - TNode atom = assertion[0]; + TNode atom = literal[0]; switch(atom.getKind()){ case kind::LEQ: //(not (LEQ x c)) <=> (GT x c) return kind::GT; @@ -201,57 +201,58 @@ inline int deltaCoeff(Kind k){ } } -template <bool selectLeft> -inline TNode getSide(TNode assertion, Kind simpleKind){ - switch(simpleKind){ - case kind::LT: - case kind::GT: - case kind::DISTINCT: - return selectLeft ? (assertion[0])[0] : (assertion[0])[1]; - case kind::LEQ: - case kind::GEQ: - case kind::EQUAL: - return selectLeft ? assertion[0] : assertion[1]; - default: - Unreachable(); - return TNode::null(); - } -} - -inline DeltaRational determineRightConstant(TNode assertion, Kind simpleKind){ - TNode right = getSide<false>(assertion, simpleKind); - - Assert(right.getKind() == kind::CONST_RATIONAL); - const Rational& noninf = right.getConst<Rational>(); - Rational inf = Rational(Integer(deltaCoeff(simpleKind))); - return DeltaRational(noninf, inf); -} - -inline DeltaRational asDeltaRational(TNode n){ - Kind simp = simplifiedKind(n); - return determineRightConstant(n, simp); -} - - /** - * Takes two nodes with exactly 2 children, - * the second child of both are of kind CONST_RATIONAL, - * and compares value of the two children. - * This is for comparing inequality nodes. - * RightHandRationalLT((<= x 50), (< x 75)) == true - */ -struct RightHandRationalLT -{ - bool operator()(TNode s1, TNode s2) const - { - TNode rh1 = s1[1]; - TNode rh2 = s2[1]; - const Rational& c1 = rh1.getConst<Rational>(); - const Rational& c2 = rh2.getConst<Rational>(); - int cmpRes = c1.cmp(c2); - return cmpRes < 0; - } -}; +// template <bool selectLeft> +// inline TNode getSide(TNode assertion, Kind simpleKind){ +// switch(simpleKind){ +// case kind::LT: +// case kind::GT: +// case kind::DISTINCT: +// return selectLeft ? (assertion[0])[0] : (assertion[0])[1]; +// case kind::LEQ: +// case kind::GEQ: +// case kind::EQUAL: +// return selectLeft ? assertion[0] : assertion[1]; +// default: +// Unreachable(); +// return TNode::null(); +// } +// } + +// inline DeltaRational determineRightConstant(TNode assertion, Kind simpleKind){ +// TNode right = getSide<false>(assertion, simpleKind); + +// Assert(right.getKind() == kind::CONST_RATIONAL); +// const Rational& noninf = right.getConst<Rational>(); + +// Rational inf = Rational(Integer(deltaCoeff(simpleKind))); +// return DeltaRational(noninf, inf); +// } + +// inline DeltaRational asDeltaRational(TNode n){ +// Kind simp = simplifiedKind(n); +// return determineRightConstant(n, simp); +// } + +// /** +// * Takes two nodes with exactly 2 children, +// * the second child of both are of kind CONST_RATIONAL, +// * and compares value of the two children. +// * This is for comparing inequality nodes. +// * RightHandRationalLT((<= x 50), (< x 75)) == true +// */ +// struct RightHandRationalLT +// { +// bool operator()(TNode s1, TNode s2) const +// { +// TNode rh1 = s1[1]; +// TNode rh2 = s2[1]; +// const Rational& c1 = rh1.getConst<Rational>(); +// const Rational& c2 = rh2.getConst<Rational>(); +// int cmpRes = c1.cmp(c2); +// return cmpRes < 0; +// } +// }; inline Node negateConjunctionAsClause(TNode conjunction){ Assert(conjunction.getKind() == kind::AND); @@ -278,6 +279,24 @@ inline Node maybeUnaryConvert(NodeBuilder<>& builder){ } } +inline void flattenAnd(Node n, std::vector<TNode>& out){ + Assert(n.getKind() == kind::AND); + for(Node::iterator i=n.begin(), i_end=n.end(); i != i_end; ++i){ + Node curr = *i; + if(curr.getKind() == kind::AND){ + flattenAnd(curr, out); + }else{ + out.push_back(curr); + } + } +} + +inline Node flattenAnd(Node n){ + std::vector<TNode> out; + flattenAnd(n, out); + return NodeManager::currentNM()->mkNode(kind::AND, out); +} + }; /* namesapce arith */ }; /* namespace theory */ }; /* namespace CVC4 */ diff --git a/src/theory/arith/arithvar.h b/src/theory/arith/arithvar.h index 52dc9fd6a..432f9f0c2 100644 --- a/src/theory/arith/arithvar.h +++ b/src/theory/arith/arithvar.h @@ -47,7 +47,17 @@ typedef __gnu_cxx::hash_map<ArithVar, Node> ArithVarToNodeMap; */ class ArithVarCallBack { public: - virtual void callback(ArithVar x) = 0; + virtual void operator()(ArithVar x) = 0; +}; + +class TNodeCallBack { +public: + virtual void operator()(TNode n) = 0; +}; + +class NodeCallBack { +public: + virtual void operator()(Node n) = 0; }; }; /* namesapce arith */ diff --git a/src/theory/arith/arithvar_set.h b/src/theory/arith/arithvar_set.h index b502849fd..b9ae48b16 100644 --- a/src/theory/arith/arithvar_set.h +++ b/src/theory/arith/arithvar_set.h @@ -322,43 +322,27 @@ public: class CDArithVarSet { private: - class RemoveIntWrapper{ - private: - ArithVar d_var; - ArithVarCallBack& d_onDestruction; - - public: - RemoveIntWrapper(ArithVar v, ArithVarCallBack& onDestruction): - d_var(v), d_onDestruction(onDestruction) - {} - - ~RemoveIntWrapper(){ - d_onDestruction.callback(d_var); - } - }; - - std::vector<bool> d_set; - context::CDList<RemoveIntWrapper> d_list; - - class OnDestruction : public ArithVarCallBack { + class RemoveIntCleanup { private: std::vector<bool>& d_set; public: - OnDestruction(std::vector<bool>& set): - d_set(set) + RemoveIntCleanup(std::vector<bool>& set) + : d_set(set) {} - void callback(ArithVar x){ - Assert(x < d_set.size()); + void operator()(ArithVar* p){ + ArithVar x = *p; + Assert(d_set[x]); d_set[x] = false; } }; - OnDestruction d_callback; + std::vector<bool> d_set; + context::CDList<ArithVar, RemoveIntCleanup> d_list; public: - CDArithVarSet(context::Context* c) : - d_list(c), d_callback(d_set) + CDArithVarSet(context::Context* c) + : d_set(), d_list(c, true, RemoveIntCleanup(d_set)) { } /** This cannot be const as garbage collection is done lazily. */ @@ -375,7 +359,7 @@ public: if(x >= d_set.size()){ d_set.resize(x+1, false); } - d_list.push_back(RemoveIntWrapper(x, d_callback)); + d_list.push_back(x); d_set[x] = true; } }; diff --git a/src/theory/arith/atom_database.cpp b/src/theory/arith/atom_database.cpp deleted file mode 100644 index 3476eb8f5..000000000 --- a/src/theory/arith/atom_database.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/********************* */ -/*! \file atom_database.cpp - ** \verbatim - ** Original author: taking - ** Major contributors: none - ** Minor contributors (to current version): mdeters - ** This file is part of the CVC4 prototype. - ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) - ** Courant Institute of Mathematical Sciences - ** New York University - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim - ** - ** \brief [[ Add one-line brief description here ]] - ** - ** [[ Add lengthier description here ]] - ** \todo document this file - **/ - -#include "theory/arith/atom_database.h" -#include "theory/arith/arith_utilities.h" - -#include <list> - -using namespace std; -using namespace CVC4::kind; - -namespace CVC4 { -namespace theory { -namespace arith { - -ArithAtomDatabase::ArithAtomDatabase(context::Context* cxt, OutputChannel& out) : - d_arithOut(out), d_setsMap() -{ } - -bool ArithAtomDatabase::leftIsSetup(TNode left) const{ - return d_setsMap.find(left) != d_setsMap.end(); -} - -const ArithAtomDatabase::VariablesSets& ArithAtomDatabase::getVariablesSets(TNode left) const{ - Assert(leftIsSetup(left)); - NodeToSetsMap::const_iterator i = d_setsMap.find(left); - return i->second; -} -ArithAtomDatabase::VariablesSets& ArithAtomDatabase::getVariablesSets(TNode left){ - Assert(leftIsSetup(left)); - NodeToSetsMap::iterator i = d_setsMap.find(left); - return i->second; -} -EqualValueSet& ArithAtomDatabase::getEqualValueSet(TNode left){ - Assert(leftIsSetup(left)); - return getVariablesSets(left).d_eqValueSet; -} - -const EqualValueSet& ArithAtomDatabase::getEqualValueSet(TNode left) const{ - Assert(leftIsSetup(left)); - return getVariablesSets(left).d_eqValueSet; -} - -BoundValueSet& ArithAtomDatabase::getBoundValueSet(TNode left){ - Assert(leftIsSetup(left)); - return getVariablesSets(left).d_boundValueSet; -} - -const BoundValueSet& ArithAtomDatabase::getBoundValueSet(TNode left) const{ - Assert(leftIsSetup(left)); - return getVariablesSets(left).d_boundValueSet; -} - -bool ArithAtomDatabase::hasAnyAtoms(TNode v) const{ - Assert(!leftIsSetup(v) - || !(getEqualValueSet(v)).empty() - || !(getBoundValueSet(v)).empty()); - - return leftIsSetup(v); -} - -void ArithAtomDatabase::setupLefthand(TNode left){ - Assert(!leftIsSetup(left)); - - d_setsMap[left] = VariablesSets(); -} - -bool ArithAtomDatabase::containsLiteral(TNode lit) const{ - switch(lit.getKind()){ - case NOT: return containsAtom(lit[0]); - default: return containsAtom(lit); - } -} - -bool ArithAtomDatabase::containsAtom(TNode atom) const{ - switch(atom.getKind()){ - case EQUAL: return containsEquality(atom); - case LEQ: return containsLeq(atom); - case GEQ: return containsGeq(atom); - default: - Unreachable(); - } -} - -bool ArithAtomDatabase::containsEquality(TNode atom) const{ - TNode left = atom[0]; - const EqualValueSet& eqSet = getEqualValueSet(left); - return eqSet.find(atom) != eqSet.end(); -} - -bool ArithAtomDatabase::containsLeq(TNode atom) const{ - TNode left = atom[0]; - const Rational& value = rightHandRational(atom); - - const BoundValueSet& bvSet = getBoundValueSet(left); - BoundValueSet::const_iterator i = bvSet.find(value); - if(i == bvSet.end()){ - return false; - }else{ - const BoundValueEntry& entry = i->second; - return entry.hasLeq(); - } -} - -bool ArithAtomDatabase::containsGeq(TNode atom) const{ - TNode left = atom[0]; - const Rational& value = rightHandRational(atom); - - const BoundValueSet& bvSet = getBoundValueSet(left); - BoundValueSet::const_iterator i = bvSet.find(value); - if(i == bvSet.end()){ - return false; - }else{ - const BoundValueEntry& entry = i->second; - return entry.hasGeq(); - } -} - -void ArithAtomDatabase::addAtom(TNode atom){ - TNode left = atom[0]; - TNode right = atom[1]; - - if(!leftIsSetup(left)){ - setupLefthand(left); - } - - const Rational& value = rightHandRational(atom); - - switch(atom.getKind()){ - case EQUAL: - { - Assert(!containsEquality(atom)); - addImplicationsUsingEqualityAndEqualityValues(atom); - addImplicationsUsingEqualityAndBoundValues(atom); - - pair<EqualValueSet::iterator, bool> res = getEqualValueSet(left).insert(atom); - Assert(res.second); - break; - } - case LEQ: - { - addImplicationsUsingLeqAndEqualityValues(atom); - addImplicationsUsingLeqAndBoundValues(atom); - - BoundValueSet& bvSet = getBoundValueSet(left); - if(hasBoundValueEntry(atom)){ - BoundValueSet::iterator i = bvSet.find(value); - BoundValueEntry& inSet = i->second; - inSet.addLeq(atom); - }else{ - bvSet.insert(make_pair(value, BoundValueEntry::mkFromLeq(atom))); - } - break; - } - case GEQ: - { - addImplicationsUsingGeqAndEqualityValues(atom); - addImplicationsUsingGeqAndBoundValues(atom); - - BoundValueSet& bvSet = getBoundValueSet(left); - if(hasBoundValueEntry(atom)){ - BoundValueSet::iterator i = bvSet.find(value); - BoundValueEntry& inSet = i->second; - inSet.addGeq(atom); - }else{ - bvSet.insert(make_pair(value, BoundValueEntry::mkFromGeq(atom))); - } - break; - } - default: - Unreachable(); - } -} - -bool ArithAtomDatabase::hasBoundValueEntry(TNode atom){ - TNode left = atom[0]; - const Rational& value = rightHandRational(atom); - BoundValueSet& bvSet = getBoundValueSet(left); - return bvSet.find(value) != bvSet.end(); -} - -bool rightHandRationalIsEqual(TNode a, TNode b){ - TNode secondA = a[1]; - TNode secondB = b[1]; - - const Rational& qA = secondA.getConst<Rational>(); - const Rational& qB = secondB.getConst<Rational>(); - - return qA == qB; -} - - -bool rightHandRationalIsLT(TNode a, TNode b){ - //This version is sticking around because it is easier to read! - return RightHandRationalLT()(a,b); -} - -void ArithAtomDatabase::addImplicationsUsingEqualityAndEqualityValues(TNode atom){ - Assert(atom.getKind() == EQUAL); - TNode left = atom[0]; - EqualValueSet& eqSet = getEqualValueSet(left); - - Node negation = NodeManager::currentNM()->mkNode(NOT, atom); - - for(EqualValueSet::iterator eqIter = eqSet.begin(), endIter = eqSet.end(); - eqIter != endIter; ++eqIter){ - TNode eq = *eqIter; - Assert(eq != atom); - addImplication(eq, negation); - } -} - -// if weaker, do not return an equivalent node -// if strict, get the strongest bound implied by (< x value) -// if !strict, get the strongest bound implied by (<= x value) -Node getUpperBound(const BoundValueSet& bvSet, const Rational& value, bool strict, bool weaker){ - BoundValueSet::const_iterator bv = bvSet.lower_bound(value); - if(bv == bvSet.end()){ - return Node::null(); - } - - if((bv->second).getValue() == value){ - const BoundValueEntry& entry = bv->second; - if(strict && entry.hasGeq() && !weaker){ - return NodeBuilder<1>(NOT) << entry.getGeq(); - }else if(entry.hasLeq() && (strict || !weaker)){ - return entry.getLeq(); - } - } - ++bv; - if(bv == bvSet.end()){ - return Node::null(); - } - Assert(bv->second.getValue() > value); - const BoundValueEntry& entry = bv->second; - if(entry.hasGeq()){ - return NodeBuilder<1>(NOT) << entry.getGeq(); - }else{ - Assert(entry.hasLeq()); - return entry.getLeq(); - } -} - - - - -// if weaker, do not return an equivalent node -// if strict, get the strongest bound implied by (> x value) -// if !strict, get the strongest bound implied by (>= x value) -Node getLowerBound(const BoundValueSet& bvSet, const Rational& value, bool strict, bool weaker){ - static int time = 0; - ++time; - - if(bvSet.empty()){ - return Node::null(); - } - Debug("getLowerBound") << "getLowerBound" << bvSet.size() << " " << value << " " << strict << weaker << endl; - - BoundValueSet::const_iterator bv = bvSet.lower_bound(value); - if(bv == bvSet.end()){ - Debug("getLowerBound") << "got end " << value << " " << (bvSet.rbegin()->second).getValue() << endl; - Assert(value > (bvSet.rbegin()->second).getValue()); - }else{ - Debug("getLowerBound") << value << ", " << bv->second.getValue() << endl; - Assert(value <= bv->second.getValue()); - } - - if(bv != bvSet.end() && (bv->second).getValue() == value){ - const BoundValueEntry& entry = bv->second; - Debug("getLowerBound") << entry.hasLeq() << entry.hasGeq() << endl; - if(strict && entry.hasLeq() && !weaker){ - return NodeBuilder<1>(NOT) << entry.getLeq(); - }else if(entry.hasGeq() && (strict || !weaker)){ - return entry.getGeq(); - } - } - if(bv == bvSet.begin()){ - return Node::null(); - }else{ - --bv; - // (and (>= x v) (>= v v')) then (> x v') - Assert(bv->second.getValue() < value); - const BoundValueEntry& entry = bv->second; - if(entry.hasLeq()){ - return NodeBuilder<1>(NOT) << entry.getLeq(); - }else{ - Assert(entry.hasGeq()); - return entry.getGeq(); - } - } -} - -void ArithAtomDatabase::addImplicationsUsingEqualityAndBoundValues(TNode atom){ - Assert(atom.getKind() == EQUAL); - Node left = atom[0]; - - const Rational& value = rightHandRational(atom); - - BoundValueSet& bvSet = getBoundValueSet(left); - Node ub = getUpperBound(bvSet, value, false, false); - Node lb = getLowerBound(bvSet, value, false, false); - - if(!ub.isNull()){ - addImplication(atom, ub); - } - - if(!lb.isNull()){ - addImplication(atom, lb); - } -} - -void ArithAtomDatabase::addImplicationsUsingLeqAndBoundValues(TNode atom) -{ - Assert(atom.getKind() == LEQ); - Node negation = NodeManager::currentNM()->mkNode(NOT, atom); - - Node ub = getImpliedUpperBoundUsingLeq(atom, false); - Node lb = getImpliedLowerBoundUsingGT(negation, false); - - if(!ub.isNull()){ - addImplication(atom, ub); - } - - if(!lb.isNull()){ - addImplication(negation, lb); - } -} - -void ArithAtomDatabase::addImplicationsUsingLeqAndEqualityValues(TNode atom) { - Assert(atom.getKind() == LEQ); - Node negation = NodeManager::currentNM()->mkNode(NOT, atom); - - TNode left = atom[0]; - EqualValueSet& eqSet = getEqualValueSet(left); - - //TODO Improve this later - for(EqualValueSet::iterator eqIter = eqSet.begin(); eqIter != eqSet.end(); ++eqIter){ - TNode eq = *eqIter; - if(rightHandRationalIsEqual(atom, eq)){ - // (x = b' /\ b = b') => x <= b - addImplication(eq, atom); - }else if(rightHandRationalIsLT(atom, eq)){ - // (x = b' /\ b' > b) => x > b - addImplication(eq, negation); - }else{ - // (x = b' /\ b' < b) => x <= b - addImplication(eq, atom); - } - } -} - - -void ArithAtomDatabase::addImplicationsUsingGeqAndBoundValues(TNode atom){ - Assert(atom.getKind() == GEQ); - Node negation = NodeManager::currentNM()->mkNode(NOT, atom); - - Node lb = getImpliedLowerBoundUsingGeq(atom, false); //What is implied by (>= left value) - Node ub = getImpliedUpperBoundUsingLT(negation, false); - - if(!lb.isNull()){ - addImplication(atom, lb); - } - - if(!ub.isNull()){ - addImplication(negation, ub); - } -} -void ArithAtomDatabase::addImplicationsUsingGeqAndEqualityValues(TNode atom){ - - Assert(atom.getKind() == GEQ); - Node negation = NodeManager::currentNM()->mkNode(NOT, atom); - Node left = atom[0]; - EqualValueSet& eqSet = getEqualValueSet(left); - - //TODO Improve this later - for(EqualValueSet::iterator eqIter = eqSet.begin(); eqIter != eqSet.end(); ++eqIter){ - TNode eq = *eqIter; - if(rightHandRationalIsEqual(atom, eq)){ - // (x = b' /\ b = b') => x >= b - addImplication(eq, atom); - }else if(rightHandRationalIsLT(eq, atom)){ - // (x = b' /\ b' < b) => x < b - addImplication(eq, negation); - }else{ - // (x = b' /\ b' > b) => x >= b - addImplication(eq, atom); - } - } -} - -void ArithAtomDatabase::addImplication(TNode a, TNode b){ - Node imp = NodeBuilder<2>(IMPLIES) << a << b; - - Debug("arith::unate") << "ArithAtomDatabase::addImplication" - << "(" << a << ", " << b <<")" << endl; - - d_arithOut.lemma(imp); -} - - -Node ArithAtomDatabase::getImpliedUpperBoundUsingLeq(TNode leq, bool weaker) const { - Assert(leq.getKind() == LEQ); - Node left = leq[0]; - - if(!leftIsSetup(left)) return Node::null(); - - const Rational& value = rightHandRational(leq); - const BoundValueSet& bvSet = getBoundValueSet(left); - - Node ub = getUpperBound(bvSet, value, false, weaker); - return ub; -} - -Node ArithAtomDatabase::getImpliedUpperBoundUsingLT(TNode lt, bool weaker) const { - Assert(lt.getKind() == NOT && lt[0].getKind() == GEQ); - Node atom = lt[0]; - Node left = atom[0]; - - if(!leftIsSetup(left)) return Node::null(); - - const Rational& value = rightHandRational(atom); - const BoundValueSet& bvSet = getBoundValueSet(left); - - return getUpperBound(bvSet, value, true, weaker); -} - -Node ArithAtomDatabase::getBestImpliedUpperBound(TNode upperBound) const { - Node result = Node::null(); - if(upperBound.getKind() == LEQ ){ - result = getImpliedUpperBoundUsingLeq(upperBound, false); - }else if(upperBound.getKind() == NOT && upperBound[0].getKind() == GEQ){ - result = getImpliedUpperBoundUsingLT(upperBound, false); - }else if(upperBound.getKind() == LT){ - Node geq = NodeBuilder<2>(GEQ) << upperBound[0] << upperBound[1]; - Node lt = NodeBuilder<1>(NOT) << geq; - result = getImpliedUpperBoundUsingLT(lt, false); - }else{ - Unreachable(); - } - - Debug("arith::unate") << upperBound <<" -> " << result << std::endl; - return result; -} - -Node ArithAtomDatabase::getWeakerImpliedUpperBound(TNode upperBound) const { - Node result = Node::null(); - if(upperBound.getKind() == LEQ ){ - result = getImpliedUpperBoundUsingLeq(upperBound, true); - }else if(upperBound.getKind() == NOT && upperBound[0].getKind() == GEQ){ - result = getImpliedUpperBoundUsingLT(upperBound, true); - }else if(upperBound.getKind() == LT){ - Node geq = NodeBuilder<2>(GEQ) << upperBound[0] << upperBound[1]; - Node lt = NodeBuilder<1>(NOT) << geq; - result = getImpliedUpperBoundUsingLT(lt, true); - }else{ - Unreachable(); - } - Assert(upperBound != result); - Debug("arith::unate") << upperBound <<" -> " << result << std::endl; - return result; -} - -Node ArithAtomDatabase::getImpliedLowerBoundUsingGT(TNode gt, bool weaker) const { - Assert(gt.getKind() == NOT && gt[0].getKind() == LEQ); - Node atom = gt[0]; - Node left = atom[0]; - - if(!leftIsSetup(left)) return Node::null(); - - const Rational& value = rightHandRational(atom); - const BoundValueSet& bvSet = getBoundValueSet(left); - - return getLowerBound(bvSet, value, true, weaker); -} - -Node ArithAtomDatabase::getImpliedLowerBoundUsingGeq(TNode geq, bool weaker) const { - Assert(geq.getKind() == GEQ); - Node left = geq[0]; - - if(!leftIsSetup(left)) return Node::null(); - - const Rational& value = rightHandRational(geq); - const BoundValueSet& bvSet = getBoundValueSet(left); - - return getLowerBound(bvSet, value, false, weaker); -} - -Node ArithAtomDatabase::getBestImpliedLowerBound(TNode lowerBound) const { - Node result = Node::null(); - if(lowerBound.getKind() == GEQ ){ - result = getImpliedLowerBoundUsingGeq(lowerBound, false); - }else if(lowerBound.getKind() == NOT && lowerBound[0].getKind() == LEQ){ - result = getImpliedLowerBoundUsingGT(lowerBound, false); - }else if(lowerBound.getKind() == GT){ - Node leq = NodeBuilder<2>(LEQ)<<lowerBound[0]<< lowerBound[1]; - Node gt = NodeBuilder<1>(NOT) << leq; - result = getImpliedLowerBoundUsingGT(gt, false); - }else{ - Unreachable(); - } - Debug("arith::unate") << lowerBound <<" -> " << result << std::endl; - return result; -} - -Node ArithAtomDatabase::getWeakerImpliedLowerBound(TNode lowerBound) const { - Node result = Node::null(); - if(lowerBound.getKind() == GEQ ){ - result = getImpliedLowerBoundUsingGeq(lowerBound, true); - }else if(lowerBound.getKind() == NOT && lowerBound[0].getKind() == LEQ){ - result = getImpliedLowerBoundUsingGT(lowerBound, true); - }else if(lowerBound.getKind() == GT){ - Node leq = NodeBuilder<2>(LEQ)<<lowerBound[0]<< lowerBound[1]; - Node gt = NodeBuilder<1>(NOT) << leq; - result = getImpliedLowerBoundUsingGT(gt, true); - }else{ - Unreachable(); - } - Assert(result != lowerBound); - - Debug("arith::unate") << lowerBound <<" -> " << result << std::endl; - return result; -} - -}; /* namesapce arith */ -}; /* namespace theory */ -}; /* namespace CVC4 */ diff --git a/src/theory/arith/atom_database.h b/src/theory/arith/atom_database.h deleted file mode 100644 index 4da8d7975..000000000 --- a/src/theory/arith/atom_database.h +++ /dev/null @@ -1,165 +0,0 @@ -/********************* */ -/*! \file atom_database.h - ** \verbatim - ** Original author: taking - ** Major contributors: none - ** Minor contributors (to current version): mdeters - ** This file is part of the CVC4 prototype. - ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) - ** Courant Institute of Mathematical Sciences - ** New York University - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim - ** - ** \brief ArithAtomDatabase keeps a database of the arithmetic atoms. - ** Importantly, ArithAtomDatabase also handles unate propagations, - ** i.e. it constructs implications of the form - ** "if x < c and c < b, then x < b" (where c and b are constants). - ** - ** ArithAtomDatabase detects unate implications amongst the atoms - ** associated with the theory of arithmetic and informs the SAT solver of the - ** implication. A unate implication is an implication of the form: - ** "if x < c and c < b, then x < b" (where c and b are constants). - ** Unate implications are always 2-SAT clauses. - ** ArithAtomDatabase sends the implications to the SAT solver in an - ** online fashion. - ** This means that atoms may be added during solving or before. - ** - ** ArithAtomDatabase maintains sorted lists containing all atoms associated - ** for each unique left hand side, the "x" in the inequality "x < c". - ** The lists are sorted by the value of the right hand side which must be a - ** rational constant. - ** - ** ArithAtomDatabase tries to send out a minimal number of additional - ** lemmas per atom added. Let (x < a), (x < b), (x < c) be arithmetic atoms s.t. - ** a < b < c. - ** If the the order of adding the atoms is (x < a), (x < b), and (x < c), then - ** then set of all lemmas added is: - ** {(=> (x<a) (x < b)), (=> (x<b) (x < c))} - ** If the order is changed to (x < a), (x < c), and (x < b), then - ** the final set of implications emitted is: - ** {(=> (x<a) (x < c)), (=> (x<a) (x < b)), (=> (x<b) (x < c))} - ** - ** \todo document this file - **/ - - - -#include "cvc4_private.h" - -#ifndef __CVC4__THEORY__ARITH__ARITH_ATOM_DATABASE_H -#define __CVC4__THEORY__ARITH__ARITH_ATOM_DATABASE_H - -#include "expr/node.h" -#include "context/context.h" - -#include "theory/output_channel.h" -#include "theory/arith/ordered_set.h" - -#include <ext/hash_map> - -namespace CVC4 { -namespace theory { -namespace arith { - -class ArithAtomDatabase { -private: - /** - * OutputChannel for the theory of arithmetic. - * The propagator uses this to pass implications back to the SAT solver. - */ - OutputChannel& d_arithOut; - - struct VariablesSets { - BoundValueSet d_boundValueSet; - EqualValueSet d_eqValueSet; - }; - - typedef __gnu_cxx::hash_map<TNode, VariablesSets, NodeHashFunction> NodeToSetsMap; - NodeToSetsMap d_setsMap; - -public: - ArithAtomDatabase(context::Context* cxt, OutputChannel& arith); - - /** - * Adds an atom to the propagator. - * Any resulting lemmas will be output via d_arithOut. - */ - void addAtom(TNode atom); - - /** Returns true if v has been added as a left hand side in an atom */ - bool hasAnyAtoms(TNode v) const; - - bool containsLiteral(TNode lit) const; - bool containsAtom(TNode atom) const; - bool containsEquality(TNode atom) const; - bool containsLeq(TNode atom) const; - bool containsGeq(TNode atom) const; - - /** Check to make sure an lhs has been properly set-up. */ - bool leftIsSetup(TNode left) const; - -private: - - VariablesSets& getVariablesSets(TNode left); - BoundValueSet& getBoundValueSet(TNode left); - EqualValueSet& getEqualValueSet(TNode left); - - const VariablesSets& getVariablesSets(TNode left) const; - const BoundValueSet& getBoundValueSet(TNode left) const; - const EqualValueSet& getEqualValueSet(TNode left) const; - - /** Sends an implication (=> a b) to the PropEngine via d_arithOut. */ - void addImplication(TNode a, TNode b); - - /** Initializes the lists associated with a unique lhs. */ - void setupLefthand(TNode left); - - - /** - * The addImplicationsUsingKAndJList(...) - * functions are the work horses of the unate part of ArithAtomDatabase. - * These take an atom of the kind K that has just been added - * to its associated list, and the ordered list of Js associated with the lhs, - * and uses these to deduce unate implications. - * (K and J vary over EQUAL, LEQ, and GEQ.) - * - * Input: - * atom - the atom being inserted of kind K - * Jset - the list of atoms of kind J associated with the lhs. - * - * Unfortunately, these tend to be an absolute bear to read because - * of all of the special casing and C++ iterator manipulation required. - */ - - void addImplicationsUsingEqualityAndEqualityValues(TNode eq); - void addImplicationsUsingEqualityAndBoundValues(TNode eq); - - void addImplicationsUsingLeqAndEqualityValues(TNode leq); - void addImplicationsUsingLeqAndBoundValues(TNode leq); - - void addImplicationsUsingGeqAndEqualityValues(TNode geq); - void addImplicationsUsingGeqAndBoundValues(TNode geq); - - bool hasBoundValueEntry(TNode n); - - Node getImpliedUpperBoundUsingLeq(TNode leq, bool weaker) const; - Node getImpliedUpperBoundUsingLT(TNode lt, bool weaker) const; - - Node getImpliedLowerBoundUsingGeq(TNode geq, bool weaker) const; - Node getImpliedLowerBoundUsingGT(TNode gt, bool weaker) const; - -public: - Node getBestImpliedUpperBound(TNode upperBound) const; - Node getBestImpliedLowerBound(TNode lowerBound) const; - - - Node getWeakerImpliedUpperBound(TNode upperBound) const; - Node getWeakerImpliedLowerBound(TNode lowerBound) const; -}; - -}/* CVC4::theory::arith namespace */ -}/* CVC4::theory namespace */ -}/* CVC4 namespace */ - -#endif /* __CVC4__THEORY__ARITH__ARITH_ATOM_DATABASE_H */ diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp new file mode 100644 index 000000000..f78ecdddf --- /dev/null +++ b/src/theory/arith/constraint.cpp @@ -0,0 +1,1130 @@ + +#include "cvc4_private.h" +#include "theory/arith/constraint.h" +#include "theory/arith/arith_utilities.h" +#include "theory/arith/normal_form.h" + +#include <ostream> +#include <algorithm> + +using namespace std; +using namespace CVC4::kind; + +namespace CVC4 { +namespace theory { +namespace arith { + +/** Given a simplifiedKind this returns the corresponding ConstraintType. */ +//ConstraintType constraintTypeOfLiteral(Kind k); +ConstraintType constraintTypeOfComparison(const Comparison& cmp){ + Kind k = cmp.comparisonKind(); + switch(k){ + case LT: + case LEQ: + { + Polynomial l = cmp.getLeft(); + if(l.leadingCoefficientIsPositive()){ // (< x c) + return UpperBound; + }else{ + return LowerBound; // (< (-x) c) + } + } + case GT: + case GEQ: + { + Polynomial l = cmp.getLeft(); + if(l.leadingCoefficientIsPositive()){ + return LowerBound; // (> x c) + }else{ + return UpperBound; // (> (-x) c) + } + } + case EQUAL: + return Equality; + case DISTINCT: + return Disequality; + default: + Unhandled(k); + } +} + +ConstraintValue::ConstraintValue(ArithVar x, ConstraintType t, const DeltaRational& v) + : d_variable(x), + d_type(t), + d_value(v), + d_database(NULL), + d_literal(Node::null()), + d_negation(NullConstraint), + d_canBePropagated(false), + d_assertionOrder(AssertionOrderSentinel), + d_proof(ProofIdSentinel), + d_split(false), + d_variablePosition() +{ + Assert(!initialized()); +} + + +std::ostream& operator<<(std::ostream& o, const Constraint c){ + return o << *c; +} + +std::ostream& operator<<(std::ostream& o, const ConstraintType t){ + switch(t){ + case LowerBound: + return o << ">="; + case UpperBound: + return o << "<="; + case Equality: + return o << "="; + case Disequality: + return o << "!="; + default: + Unreachable(); + } +} + +std::ostream& operator<<(std::ostream& o, const ConstraintValue& c){ + o << c.getVariable() << ' ' << c.getType() << ' ' << c.getValue(); + if(c.hasLiteral()){ + o << "(node " << c.getLiteral() << ')'; + } + return o; +} + +std::ostream& operator<<(std::ostream& o, const ValueCollection& vc){ + o << "{"; + bool pending = false; + if(vc.hasEquality()){ + o << "eq: " << vc.getEquality(); + pending = true; + } + if(vc.hasLowerBound()){ + if(pending){ + o << ", "; + } + o << "lb: " << vc.getLowerBound(); + pending = true; + } + if(vc.hasUpperBound()){ + if(pending){ + o << ", "; + } + o << "ub: " << vc.getUpperBound(); + pending = true; + } + if(vc.hasDisequality()){ + if(pending){ + o << ", "; + } + o << "de: " << vc.getDisequality(); + } + return o << "}"; +} + +void ConstraintValue::debugPrint() const { + cout << *this << endl; +} + +void ValueCollection::push_into(std::vector<Constraint>& vec) const { + Debug("arith::constraint") << "push_into " << *this << endl; + if(hasEquality()){ + vec.push_back(d_equality); + } + if(hasLowerBound()){ + vec.push_back(d_lowerBound); + } + if(hasUpperBound()){ + vec.push_back(d_upperBound); + } + if(hasDisequality()){ + vec.push_back(d_disequality); + } +} + +ValueCollection ValueCollection::mkFromConstraint(Constraint c){ + ValueCollection ret; + Assert(ret.empty()); + switch(c->getType()){ + case LowerBound: + ret.d_lowerBound = c; + break; + case UpperBound: + ret.d_upperBound = c; + break; + case Equality: + ret.d_equality = c; + break; + case Disequality: + ret.d_disequality = c; + break; + default: + Unreachable(); + } + return ret; +} + +bool ValueCollection::hasConstraintOfType(ConstraintType t) const{ + switch(t){ + case LowerBound: + return hasLowerBound(); + case UpperBound: + return hasUpperBound(); + case Equality: + return hasEquality(); + case Disequality: + return hasDisequality(); + default: + Unreachable(); + } +} + +ArithVar ValueCollection::getVariable() const{ + Assert(!empty()); + return nonNull()->getVariable(); +} + +const DeltaRational& ValueCollection::getValue() const{ + Assert(!empty()); + return nonNull()->getValue(); +} + +void ValueCollection::add(Constraint c){ + Assert(c != NullConstraint); + + Assert(empty() || getVariable() == c->getVariable()); + Assert(empty() || getValue() == c->getValue()); + + switch(c->getType()){ + case LowerBound: + Assert(!hasLowerBound()); + d_lowerBound = c; + break; + case Equality: + Assert(!hasEquality()); + d_equality = c; + break; + case UpperBound: + Assert(!hasUpperBound()); + d_upperBound = c; + break; + case Disequality: + Assert(!hasDisequality()); + d_disequality = c; + break; + default: + Unreachable(); + } +} + +Constraint ValueCollection::getConstraintOfType(ConstraintType t) const{ + switch(t){ + case LowerBound: + Assert(hasLowerBound()); + return d_lowerBound; + case Equality: + Assert(hasEquality()); + return d_equality; + case UpperBound: + Assert(hasUpperBound()); + return d_upperBound; + case Disequality: + Assert(hasDisequality()); + return d_disequality; + default: + Unreachable(); + } +} + +void ValueCollection::remove(ConstraintType t){ + switch(t){ + case LowerBound: + Assert(hasLowerBound()); + d_lowerBound = NullConstraint; + break; + case Equality: + Assert(hasEquality()); + d_equality = NullConstraint; + break; + case UpperBound: + Assert(hasUpperBound()); + d_upperBound = NullConstraint; + break; + case Disequality: + Assert(hasDisequality()); + d_disequality = NullConstraint; + break; + default: + Unreachable(); + } +} + +bool ValueCollection::empty() const{ + return + !(hasLowerBound() || + hasUpperBound() || + hasEquality() || + hasDisequality()); +} + +Constraint ValueCollection::nonNull() const{ + //This can be optimized by caching, but this is not necessary yet! + /* "Premature optimization is the root of all evil." */ + if(hasLowerBound()){ + return d_lowerBound; + }else if(hasUpperBound()){ + return d_upperBound; + }else if(hasEquality()){ + return d_equality; + }else if(hasDisequality()){ + return d_disequality; + }else{ + return NullConstraint; + } +} + +bool ConstraintValue::initialized() const { + return d_database != NULL; +} + +void ConstraintValue::initialize(ConstraintDatabase* db, SortedConstraintMapIterator v, Constraint negation){ + Assert(!initialized()); + d_database = db; + d_variablePosition = v; + d_negation = negation; +} + +ConstraintValue::~ConstraintValue() { + Assert(safeToGarbageCollect()); + + if(initialized()){ + ValueCollection& vc = d_variablePosition->second; + Debug("arith::constraint") << "removing" << vc << endl; + + vc.remove(getType()); + + if(vc.empty()){ + Debug("arith::constraint") << "erasing" << vc << endl; + SortedConstraintMap& perVariable = d_database->getVariableSCM(getVariable()); + perVariable.erase(d_variablePosition); + } + + if(hasLiteral()){ + d_database->d_nodetoConstraintMap.erase(getLiteral()); + } + } +} + +const ValueCollection& ConstraintValue::getValueCollection() const{ + return d_variablePosition->second; +} + +Constraint ConstraintValue::getCeiling() { + Debug("getCeiling") << "ConstraintValue::getCeiling on " << *this << endl; + Assert(getValue().getInfinitesimalPart().sgn() > 0); + + DeltaRational ceiling(getValue().ceiling()); + +#warning "Optimize via the iterator" + return d_database->getConstraint(getVariable(), getType(), ceiling); +} + +Constraint ConstraintValue::getFloor() { + Assert(getValue().getInfinitesimalPart().sgn() < 0); + + DeltaRational floor(Rational(getValue().floor())); + +#warning "Optimize via the iterator" + return d_database->getConstraint(getVariable(), getType(), floor); +} + +void ConstraintValue::setCanBePropagated() { + Assert(!canBePropagated()); + d_database->pushCanBePropagatedWatch(this); +} + +void ConstraintValue::setAssertedToTheTheory() { + Assert(hasLiteral()); + Assert(!assertedToTheTheory()); + Assert(!d_negation->assertedToTheTheory()); + d_database->pushAssertionOrderWatch(this); +} + +bool ConstraintValue::isSelfExplaining() const { + return d_proof == d_database->d_selfExplainingProof; +} + +bool ConstraintValue::hasEqualityEngineProof() const { + return d_proof == d_database->d_equalityEngineProof; +} + +bool ConstraintValue::sanityChecking(Node n) const { + Comparison cmp = Comparison::parseNormalForm(n); + Kind k = cmp.comparisonKind(); + Polynomial pleft = cmp.normalizedVariablePart(); + Assert(k == EQUAL || k == DISTINCT || pleft.leadingCoefficientIsPositive()); + Assert(k != EQUAL || Monomial::isMember(n[0])); + Assert(k != DISTINCT || Monomial::isMember(n[0][0])); + + TNode left = pleft.getNode(); + DeltaRational right = cmp.normalizedDeltaRational(); + + const ArithVarNodeMap& av2node = d_database->getArithVarNodeMap(); + + Debug("nf::tmp") << cmp.getNode() << endl; + Debug("nf::tmp") << k << endl; + Debug("nf::tmp") << pleft.getNode() << endl; + Debug("nf::tmp") << left << endl; + Debug("nf::tmp") << right << endl; + Debug("nf::tmp") << getValue() << endl; + Debug("nf::tmp") << av2node.hasArithVar(left) << endl; + Debug("nf::tmp") << av2node.asArithVar(left) << endl; + Debug("nf::tmp") << getVariable() << endl; + + + if(av2node.hasArithVar(left) && + av2node.asArithVar(left) == getVariable() && + getValue() == right){ + switch(getType()){ + case LowerBound: + case UpperBound: + //Be overapproximate + return k == GT || k == GEQ ||k == LT || k == LEQ; + case Equality: + return k == EQUAL; + case Disequality: + return k == DISTINCT; + default: + Unreachable(); + } + }else{ + return false; + } +} + +Constraint ConstraintValue::makeNegation(ArithVar v, ConstraintType t, const DeltaRational& r){ + switch(t){ + case LowerBound: + { + Assert(r.infinitesimalSgn() >= 0); + if(r.infinitesimalSgn() > 0){ + Assert(r.getInfinitesimalPart() == 1); + // make (not (v > r)), which is (v <= r) + DeltaRational dropInf(r.getNoninfinitesimalPart(), 0); + return new ConstraintValue(v, UpperBound, dropInf); + }else{ + Assert(r.infinitesimalSgn() == 0); + // make (not (v >= r)), which is (v < r) + DeltaRational addInf(r.getNoninfinitesimalPart(), -1); + return new ConstraintValue(v, UpperBound, addInf); + } + } + case UpperBound: + { + Assert(r.infinitesimalSgn() <= 0); + if(r.infinitesimalSgn() < 0){ + Assert(r.getInfinitesimalPart() == -1); + // make (not (v < r)), which is (v >= r) + DeltaRational dropInf(r.getNoninfinitesimalPart(), 0); + return new ConstraintValue(v, LowerBound, dropInf); + }else{ + Assert(r.infinitesimalSgn() == 0); + // make (not (v <= r)), which is (v > r) + DeltaRational addInf(r.getNoninfinitesimalPart(), 1); + return new ConstraintValue(v, LowerBound, addInf); + } + } + case Equality: + return new ConstraintValue(v, Disequality, r); + case Disequality: + return new ConstraintValue(v, Equality, r); + default: + Unreachable(); + return NullConstraint; + } +} + +ConstraintDatabase::ConstraintDatabase(context::Context* satContext, context::Context* userContext, const ArithVarNodeMap& av2nodeMap, + DifferenceManager& dm) + : d_varDatabases(), + d_toPropagate(satContext), + d_proofs(satContext, false), + d_watches(new Watches(satContext, userContext)), + d_av2nodeMap(av2nodeMap), + d_differenceManager(dm), + d_satContext(satContext), + d_satAllocationLevel(d_satContext->getLevel()) +{ + d_selfExplainingProof = d_proofs.size(); + d_proofs.push_back(NullConstraint); + + d_equalityEngineProof = d_proofs.size(); + d_proofs.push_back(NullConstraint); +} + +Constraint ConstraintDatabase::getConstraint(ArithVar v, ConstraintType t, const DeltaRational& r){ + //This must always return a constraint. + + SortedConstraintMap& scm = getVariableSCM(v); + pair<SortedConstraintMapIterator, bool> insertAttempt; + insertAttempt = scm.insert(make_pair(r, ValueCollection())); + + SortedConstraintMapIterator pos = insertAttempt.first; + ValueCollection& vc = pos->second; + if(vc.hasConstraintOfType(t)){ + return vc.getConstraintOfType(t); + }else{ + Constraint c = new ConstraintValue(v, t, r); + Constraint negC = ConstraintValue::makeNegation(v, t, r); + + SortedConstraintMapIterator negPos; + if(t == Equality || t == Disequality){ + negPos = pos; + }else{ + pair<SortedConstraintMapIterator, bool> negInsertAttempt; + negInsertAttempt = scm.insert(make_pair(negC->getValue(), ValueCollection())); + Assert(negInsertAttempt.second); + negPos = negInsertAttempt.first; + } + + c->initialize(this, pos, negC); + negC->initialize(this, negPos, c); + + vc.add(c); + negPos->second.add(negC); + + return c; + } +} +bool ConstraintDatabase::emptyDatabase(const std::vector<PerVariableDatabase>& vec){ + std::vector<PerVariableDatabase>::const_iterator first = vec.begin(); + std::vector<PerVariableDatabase>::const_iterator last = vec.end(); + return std::find_if(first, last, PerVariableDatabase::IsEmpty) == last; +} + +ConstraintDatabase::~ConstraintDatabase(){ + Assert(d_satAllocationLevel <= d_satContext->getLevel()); + + delete d_watches; + + std::vector<Constraint> constraintList; + + while(!d_varDatabases.empty()){ + PerVariableDatabase* back = d_varDatabases.back(); + + SortedConstraintMap& scm = back->d_constraints; + SortedConstraintMapIterator i = scm.begin(), i_end = scm.end(); + for(; i != i_end; ++i){ + (i->second).push_into(constraintList); + } + while(!constraintList.empty()){ + Constraint c = constraintList.back(); + constraintList.pop_back(); + delete c; + } + Assert(scm.empty()); + d_varDatabases.pop_back(); + delete back; + } + + Assert(d_nodetoConstraintMap.empty()); +} + +void ConstraintDatabase::addVariable(ArithVar v){ + Assert(v == d_varDatabases.size()); + d_varDatabases.push_back(new PerVariableDatabase(v)); +} + +bool ConstraintValue::safeToGarbageCollect() const{ + return !isSplit() + && !canBePropagated() + && !hasProof() + && !assertedToTheTheory(); +} + +Node ConstraintValue::split(){ + Assert(isEquality() || isDisequality()); + + bool isEq = isEquality(); + + Constraint eq = isEq ? this : d_negation; + Constraint diseq = isEq ? d_negation : this; + + TNode eqNode = eq->getLiteral(); + Assert(eqNode.getKind() == kind::EQUAL); + TNode lhs = eqNode[0]; + TNode rhs = eqNode[1]; + + Node ltNode = NodeBuilder<2>(kind::LT) << lhs << rhs; + Node gtNode = NodeBuilder<2>(kind::GT) << lhs << rhs; + + Node lemma = NodeBuilder<3>(OR) << eqNode << ltNode << gtNode; + + + eq->d_database->pushSplitWatch(eq); + diseq->d_database->pushSplitWatch(diseq); + + return lemma; +} + +bool ConstraintDatabase::hasLiteral(TNode literal) const { + return lookup(literal) != NullConstraint; +} + +// Constraint ConstraintDatabase::addLiteral(TNode literal){ +// Assert(!hasLiteral(literal)); +// bool isNot = (literal.getKind() == NOT); +// TNode atom = isNot ? literal[0] : literal; + +// Constraint atomC = addAtom(atom); + +// return isNot ? atomC->d_negation : atomC; +// } + +// Constraint ConstraintDatabase::allocateConstraintForComparison(ArithVar v, const Comparison cmp){ +// Debug("arith::constraint") << "allocateConstraintForLiteral(" << v << ", "<< cmp <<")" << endl; +// Kind kind = cmp.comparisonKind(); +// ConstraintType type = constraintTypeOfLiteral(kind); + +// DeltaRational dr = cmp.getDeltaRational(); +// return new ConstraintValue(v, type, dr); +// } + +Constraint ConstraintDatabase::addLiteral(TNode literal){ + Assert(!hasLiteral(literal)); + bool isNot = (literal.getKind() == NOT); + Node atomNode = (isNot ? literal[0] : literal); + Node negationNode = atomNode.notNode(); + + Assert(!hasLiteral(atomNode)); + Assert(!hasLiteral(negationNode)); + Comparison posCmp = Comparison::parseNormalForm(atomNode); + + ConstraintType posType = constraintTypeOfComparison(posCmp); + + Polynomial nvp = posCmp.normalizedVariablePart(); + Debug("nf::tmp") << "here " << nvp.getNode() << " " << endl; + ArithVar v = d_av2nodeMap.asArithVar(nvp.getNode()); + + DeltaRational posDR = posCmp.normalizedDeltaRational(); + + Constraint posC = new ConstraintValue(v, posType, posDR); + + Debug("arith::constraint") << "addliteral( literal ->" << literal << ")" << endl; + Debug("arith::constraint") << "addliteral( posC ->" << posC << ")" << endl; + + SortedConstraintMap& scm = getVariableSCM(posC->getVariable()); + pair<SortedConstraintMapIterator, bool> insertAttempt; + insertAttempt = scm.insert(make_pair(posC->getValue(), ValueCollection())); + + SortedConstraintMapIterator posI = insertAttempt.first; + // If the attempt succeeds, i points to a new empty ValueCollection + // If the attempt fails, i points to a pre-existing ValueCollection + + if(posI->second.hasConstraintOfType(posC->getType())){ + //This is the situation where the Constraint exists, but + //the literal has not been associated with it. + Constraint hit = posI->second.getConstraintOfType(posC->getType()); + Debug("arith::constraint") << "hit " << hit << endl; + Debug("arith::constraint") << "posC " << posC << endl; + + delete posC; + + hit->setLiteral(atomNode); + hit->getNegation()->setLiteral(negationNode); + return isNot ? hit->getNegation(): hit; + }else{ + Comparison negCmp = Comparison::parseNormalForm(negationNode); + + ConstraintType negType = constraintTypeOfComparison(negCmp); + DeltaRational negDR = negCmp.normalizedDeltaRational(); + + Constraint negC = new ConstraintValue(v, negType, negDR); + + SortedConstraintMapIterator negI; + + if(posC->isEquality()){ + negI = posI; + }else{ + Assert(posC->isLowerBound() || posC->isUpperBound()); + + pair<SortedConstraintMapIterator, bool> negInsertAttempt; + negInsertAttempt = scm.insert(make_pair(negC->getValue(), ValueCollection())); + + Debug("nf::tmp") << "sdhjfgdhjkldfgljkhdfg" << endl; + Debug("nf::tmp") << negC << endl; + Debug("nf::tmp") << negC->getValue() << endl; + + //This should always succeed as the DeltaRational for the negation is unique! + Assert(negInsertAttempt.second); + + negI = negInsertAttempt.first; + } + + (posI->second).add(posC); + (negI->second).add(negC); + + posC->initialize(this, posI, negC); + negC->initialize(this, negI, posC); + + posC->setLiteral(atomNode); + negC->setLiteral(negationNode); + + return isNot ? negC : posC; + } +} + +// ConstraintType constraintTypeOfLiteral(Kind k){ +// switch(k){ +// case LT: +// case LEQ: +// return UpperBound; +// case GT: +// case GEQ: +// return LowerBound; +// case EQUAL: +// return Equality; +// case DISTINCT: +// return Disequality; +// default: +// Unreachable(); +// } +// } + +Constraint ConstraintDatabase::lookup(TNode literal) const{ + NodetoConstraintMap::const_iterator iter = d_nodetoConstraintMap.find(literal); + if(iter == d_nodetoConstraintMap.end()){ + return NullConstraint; + }else{ + return iter->second; + } +} + +void ConstraintValue::selfExplaining(){ + markAsTrue(); +} + +void ConstraintValue::propagate(){ + Assert(hasProof()); + Assert(canBePropagated()); + Assert(!assertedToTheTheory()); + Assert(!isSelfExplaining()); + + d_database->d_toPropagate.push(this); +} + +void ConstraintValue::propagate(Constraint a){ + Assert(!hasProof()); + Assert(canBePropagated()); + + markAsTrue(a); + propagate(); +} + +void ConstraintValue::propagate(Constraint a, Constraint b){ + Assert(!hasProof()); + Assert(canBePropagated()); + + markAsTrue(a, b); + propagate(); +} + +void ConstraintValue::propagate(const std::vector<Constraint>& b){ + Assert(!hasProof()); + Assert(canBePropagated()); + + markAsTrue(b); + propagate(); +} + +void ConstraintValue::impliedBy(Constraint a){ + Assert(!isTrue()); + Assert(!getNegation()->isTrue()); + + markAsTrue(a); + if(canBePropagated()){ + propagate(); + } +} + +void ConstraintValue::impliedBy(Constraint a, Constraint b){ + Assert(!isTrue()); + Assert(!getNegation()->isTrue()); + + markAsTrue(a, b); + if(canBePropagated()){ + propagate(); + } +} + +void ConstraintValue::impliedBy(const std::vector<Constraint>& b){ + Assert(!isTrue()); + Assert(!getNegation()->isTrue()); + + markAsTrue(b); + if(canBePropagated()){ + propagate(); + } +} + +void ConstraintValue::setEqualityEngineProof(){ + Assert(truthIsUnknown()); + Assert(hasLiteral()); + d_database->pushProofWatch(this, d_database->d_equalityEngineProof); +} + +void ConstraintValue::markAsTrue(){ + Assert(truthIsUnknown()); + Assert(hasLiteral()); + Assert(assertedToTheTheory()); + d_database->pushProofWatch(this, d_database->d_selfExplainingProof); +} + +void ConstraintValue::markAsTrue(Constraint imp){ + Assert(truthIsUnknown()); + Assert(imp->hasProof()); + + d_database->d_proofs.push_back(NullConstraint); + d_database->d_proofs.push_back(imp); + ProofId proof = d_database->d_proofs.size() - 1; + d_database->pushProofWatch(this, proof); +} + +void ConstraintValue::markAsTrue(Constraint impA, Constraint impB){ + Assert(truthIsUnknown()); + Assert(impA->hasProof()); + Assert(impB->hasProof()); + + d_database->d_proofs.push_back(NullConstraint); + d_database->d_proofs.push_back(impA); + d_database->d_proofs.push_back(impB); + ProofId proof = d_database->d_proofs.size() - 1; + + d_database->pushProofWatch(this, proof); +} + +void ConstraintValue::markAsTrue(const vector<Constraint>& a){ + Assert(truthIsUnknown()); + Assert(a.size() >= 1); + d_database->d_proofs.push_back(NullConstraint); + for(vector<Constraint>::const_iterator i = a.begin(), end = a.end(); i != end; ++i){ + Constraint c_i = *i; + Assert(c_i->hasProof()); + d_database->d_proofs.push_back(c_i); + } + + ProofId proof = d_database->d_proofs.size() - 1; + + d_database->pushProofWatch(this, proof); +} + +SortedConstraintMap& ConstraintValue::constraintSet() const{ + Assert(d_database->variableDatabaseIsSetup(d_variable)); + return (d_database->d_varDatabases[d_variable])->d_constraints; +} + +bool ConstraintValue::proofIsEmpty() const{ + Assert(hasProof()); + bool result = d_database->d_proofs[d_proof] == NullConstraint; + Assert((!result) || isSelfExplaining() || hasEqualityEngineProof()); + return result; +} + +void ConstraintValue::explainBefore(NodeBuilder<>& nb, AssertionOrder order) const{ + Assert(hasProof()); + Assert(!isSelfExplaining() || assertedToTheTheory()); + + if(assertedBefore(order)){ + nb << getLiteral(); + }else if(hasEqualityEngineProof()){ + d_database->eeExplain(this, nb); + }else{ + Assert(!isSelfExplaining()); + ProofId p = d_proof; + Constraint antecedent = d_database->d_proofs[p]; + + for(; antecedent != NullConstraint; antecedent = d_database->d_proofs[--p] ){ + antecedent->explainBefore(nb, order); + } + } +} +Node ConstraintValue::explainBefore(AssertionOrder order) const{ + Assert(hasProof()); + Assert(!isSelfExplaining() || assertedBefore(order)); + if(assertedBefore(order)){ + return getLiteral(); + }else if(hasEqualityEngineProof()){ + return d_database->eeExplain(this); + }else{ + Assert(!proofIsEmpty()); + //Force the selection of the layer above if the node is assertedToTheTheory()! + if(d_database->d_proofs[d_proof-1] == NullConstraint){ + Constraint antecedent = d_database->d_proofs[d_proof]; + return antecedent->explainBefore(order); + }else{ + NodeBuilder<> nb(kind::AND); + Assert(!isSelfExplaining()); + + ProofId p = d_proof; + Constraint antecedent = d_database->d_proofs[p]; + for(; antecedent != NullConstraint; antecedent = d_database->d_proofs[--p] ){ + antecedent->explainBefore(nb, order); + } + return nb; + } + } +} + +Node ConstraintValue::explainConflict(Constraint a, Constraint b){ + NodeBuilder<> nb(kind::AND); + a->explainForConflict(nb); + b->explainForConflict(nb); + return nb; +} + +Node ConstraintValue::explainConflict(Constraint a, Constraint b, Constraint c){ + NodeBuilder<> nb(kind::AND); + a->explainForConflict(nb); + b->explainForConflict(nb); + c->explainForConflict(nb); + return nb; +} + +Constraint ConstraintValue::getStrictlyWeakerLowerBound(bool hasLiteral, bool asserted) const { + Assert(initialized()); + Assert(!asserted || hasLiteral); + + SortedConstraintMapConstIterator i = d_variablePosition; + const SortedConstraintMap& scm = constraintSet(); + SortedConstraintMapConstIterator i_begin = scm.begin(); + while(i != i_begin){ + --i; + const ValueCollection& vc = i->second; + if(vc.hasLowerBound()){ + Constraint weaker = vc.getLowerBound(); + + // asserted -> hasLiteral + // hasLiteral -> weaker->hasLiteral() + // asserted -> weaker->assertedToTheTheory() + if((!hasLiteral || (weaker->hasLiteral())) && + (!asserted || ( weaker->assertedToTheTheory()))){ + return weaker; + } + } + } + return NullConstraint; +} + +Constraint ConstraintValue::getStrictlyWeakerUpperBound(bool hasLiteral, bool asserted) const { + SortedConstraintMapConstIterator i = d_variablePosition; + const SortedConstraintMap& scm = constraintSet(); + SortedConstraintMapConstIterator i_end = scm.end(); + + ++i; + for(; i != i_end; ++i){ + const ValueCollection& vc = i->second; + if(vc.hasUpperBound()){ + Constraint weaker = vc.getUpperBound(); + if((!hasLiteral || (weaker->hasLiteral())) && + (!asserted || ( weaker->assertedToTheTheory()))){ + return weaker; + } + } + } + + return NullConstraint; +} + +Constraint ConstraintDatabase::getBestImpliedBound(ArithVar v, ConstraintType t, const DeltaRational& r) const { + Assert(variableDatabaseIsSetup(v)); + Assert(t == UpperBound || t == LowerBound); + + SortedConstraintMap& scm = getVariableSCM(v); + if(t == UpperBound){ + SortedConstraintMapConstIterator i = scm.lower_bound(r); + SortedConstraintMapConstIterator i_end = scm.end(); + Assert(i == i_end || r <= i->first); + for(; i != i_end; i++){ + Assert(r <= i->first); + const ValueCollection& vc = i->second; + if(vc.hasUpperBound()){ + return vc.getUpperBound(); + } + } + return NullConstraint; + }else{ + Assert(t == LowerBound); + if(scm.empty()){ + return NullConstraint; + }else{ + SortedConstraintMapConstIterator i = scm.lower_bound(r); + SortedConstraintMapConstIterator i_begin = scm.begin(); + SortedConstraintMapConstIterator i_end = scm.end(); + Assert(i == i_end || r <= i->first); + + int fdj = 0; + + if(i == i_end){ + --i; + Debug("getBestImpliedBound") << fdj++ << " " << r << " " << i->first << endl; + }else if( (i->first) > r){ + if(i == i_begin){ + return NullConstraint; + }else{ + --i; + Debug("getBestImpliedBound") << fdj++ << " " << r << " " << i->first << endl; + } + } + + do{ + Debug("getBestImpliedBound") << fdj++ << " " << r << " " << i->first << endl; + Assert(r >= i->first); + const ValueCollection& vc = i->second; + + if(vc.hasLowerBound()){ + return vc.getLowerBound(); + } + + if(i == i_begin){ + break; + }else{ + --i; + } + }while(true); + return NullConstraint; + } + } +} +Node ConstraintDatabase::eeExplain(const ConstraintValue* const c) const{ + Assert(c->hasLiteral()); + return d_differenceManager.explain(c->getLiteral()); +} + +void ConstraintDatabase::eeExplain(const ConstraintValue* const c, NodeBuilder<>& nb) const{ + Assert(c->hasLiteral()); + d_differenceManager.explain(c->getLiteral(), nb); +} + +bool ConstraintDatabase::variableDatabaseIsSetup(ArithVar v) const { + return v < d_varDatabases.size(); +} + + +ConstraintDatabase::Watches::Watches(context::Context* satContext, context::Context* userContext): + d_proofWatches(satContext), + d_canBePropagatedWatches(satContext), + d_assertionOrderWatches(satContext), + d_splitWatches(userContext) +{} + + +void ConstraintValue::setLiteral(Node n) { + Assert(!hasLiteral()); + Assert(sanityChecking(n)); + d_literal = n; + NodetoConstraintMap& map = d_database->d_nodetoConstraintMap; + Assert(map.find(n) == map.end()); + map.insert(make_pair(d_literal, this)); +} + +void implies(std::vector<Node>& out, Constraint a, Constraint b){ + Node la = a->getLiteral(); + Node lb = b->getLiteral(); + + Node neg_la = (la.getKind() == kind::NOT)? la[0] : la.notNode(); + + Assert(lb != neg_la); + Node orderOr = (lb < neg_la) ? lb.orNode(neg_la) : neg_la.orNode(lb); + out.push_back(orderOr); +} + +void mutuallyExclusive(std::vector<Node>& out, Constraint a, Constraint b){ + Node la = a->getLiteral(); + Node lb = b->getLiteral(); + + Node neg_la = (la.getKind() == kind::NOT)? la[0] : la.notNode(); + Node neg_lb = (lb.getKind() == kind::NOT)? lb[0] : lb.notNode(); + + Assert(neg_la != neg_lb); + Node orderOr = (neg_la < neg_lb) ? neg_la.orNode(neg_lb) : neg_lb.orNode(neg_la); + out.push_back(orderOr); +} + +void ConstraintDatabase::outputAllUnateLemmas(std::vector<Node>& out, ArithVar v) const{ + SortedConstraintMap& scm = getVariableSCM(v); + + SortedConstraintMapConstIterator outer; + SortedConstraintMapConstIterator scm_end = scm.end(); + + vector<Constraint> equalities; + for(outer = scm.begin(); outer != scm_end; ++outer){ + const ValueCollection& vc = outer->second; + if(vc.hasEquality()){ + Constraint eq = vc.getEquality(); + if(eq->hasLiteral()){ + equalities.push_back(eq); + } + } + } + + Constraint prev = NullConstraint; + //get transitive unates + //Only lower bounds or upperbounds should be done. + for(outer = scm.begin(); outer != scm_end; ++outer){ + const ValueCollection& vc = outer->second; + + if(vc.hasUpperBound()){ + Constraint ub = vc.getUpperBound(); + if(ub->hasLiteral()){ + if(prev != NullConstraint){ + implies(out, prev, ub); + } + prev = ub; + } + } + } + vector<Constraint>::const_iterator i, j, eq_end = equalities.end(); + for(i = equalities.begin(); i != eq_end; ++i){ + Constraint at_i = *i; + for(j= i + 1; j != eq_end; ++j){ + Constraint at_j = *j; + + mutuallyExclusive(out, at_i, at_j); + } + } + + for(i = equalities.begin(); i != eq_end; ++i){ + Constraint eq = *i; + const ValueCollection& vc = eq->getValueCollection(); + Assert(vc.hasEquality() && vc.getEquality()->hasLiteral()); + + bool hasLB = vc.hasLowerBound() && vc.getLowerBound()->hasLiteral(); + bool hasUB = vc.hasUpperBound() && vc.getUpperBound()->hasLiteral(); + + Constraint lb = hasLB ? + vc.getLowerBound() : eq->getStrictlyWeakerLowerBound(true, false); + Constraint ub = hasUB ? + vc.getUpperBound() : eq->getStrictlyWeakerUpperBound(true, false); + + if(hasUB && hasLB && !eq->isSplit()){ + out.push_back(eq->split()); + } + if(lb != NullConstraint){ + implies(out, eq, lb); + } + if(ub != NullConstraint){ + implies(out, eq, ub); + } + } + } + +void ConstraintDatabase::outputAllUnateLemmas(std::vector<Node>& lemmas) const{ + for(ArithVar v = 0, N = d_varDatabases.size(); v < N; ++v){ + outputAllUnateLemmas(lemmas, v); + } +} + + +}/* arith namespace */ +}/* theory namespace */ +}/* CVC4 namespace */ diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h new file mode 100644 index 000000000..e1939159b --- /dev/null +++ b/src/theory/arith/constraint.h @@ -0,0 +1,837 @@ +/********************* */ +/*! \file constraint.h + ** \verbatim + ** Original author: taking + ** Major contributors: none + ** Minor contributors (to current version): none + ** This file is part of the CVC4 prototype. + ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) + ** Courant Institute of Mathematical Sciences + ** New York University + ** See the file COPYING in the top-level source directory for licensing + ** information.\endverbatim + ** + ** \brief Defines Constraint and ConstraintDatabase which is the internal representation of variables in arithmetic + ** + ** This file defines Constraint and ConstraintDatabase. + ** A Constraint is the internal representation of literals in TheoryArithmetic. + ** Constraints are fundamentally a triple: + ** - ArithVar associated with the constraint, + ** - a DeltaRational value, + ** - and a ConstraintType. + ** + ** Literals: + ** The constraint may also keep track of a node corresponding to the + ** Constraint. + ** This can be accessed by getLiteral() in O(1) if it has been set. + ** This node must be in normal form and may be used for communication with + ** the TheoryEngine. + ** + ** In addition, Constraints keep track of the following: + ** - A Constrain that is the negation of the Constraint. + ** - An iterator into a set of Constraints for the ArithVar sorted by + ** DeltaRational value. + ** - A context dependent internal proof of the node that can be used for + ** explanations. + ** - Whether an equality/disequality has been split in the user context via a + ** lemma. + ** - Whether a constraint, be be used in explanations sent to the context + ** + ** Looking up constraints: + ** - All of the Constraints with associated nodes in the ConstraintDatabase can + ** be accessed via a single hashtable lookup until the Constraint is removed. + ** - Nodes that have not been associated to a constraints can be + ** inserted/associated to existing nodes in O(log n) time. + ** + ** Implications: + ** - A Constraint can be used to find unate implications. + ** - A unate implication is an implication based purely on the ArithVar matching + ** and the DeltaRational value. + ** (implies (<= x c) (<= x d)) given c <= d + ** - This is done using the iterator into the sorted set of constraints. + ** - Given a tight constraint and previous tightest constraint, this will + ** efficiently propagate internally. + ** + ** Additing and Removing Constraints + ** - Adding Constraints takes O(log n) time where n is the number of + ** constraints associated with the ArithVar. + ** - Removing Constraints takes O(1) time. + ** + ** Internals: + ** - Constraints are pointers to ConstraintValues. + ** - Undefined Constraints are NullConstraint. + **/ + +#include "cvc4_private.h" + +#ifndef __CVC4__THEORY__ARITH__CONSTRAINT_H +#define __CVC4__THEORY__ARITH__CONSTRAINT_H + +#include "expr/node.h" + +#include "context/context.h" +#include "context/cdlist.h" +#include "context/cdqueue.h" + +#include "theory/arith/arithvar.h" +#include "theory/arith/arithvar_node_map.h" +#include "theory/arith/delta_rational.h" + +#include "theory/arith/difference_manager.h" + +#include "theory/arith/constraint_forward.h" + +#include <vector> +#include <list> +#include <set> +#include <ext/hash_map> + +namespace CVC4 { +namespace theory { +namespace arith { + +/** + * The types of constraints. + * The convex constraints are the constraints are LowerBound, Equality, + * and UpperBound. + */ +enum ConstraintType {LowerBound, Equality, UpperBound, Disequality}; + + +typedef context::CDList<Constraint> CDConstraintList; + +typedef __gnu_cxx::hash_map<Node, Constraint, NodeHashFunction> NodetoConstraintMap; + +typedef size_t ProofId; +static ProofId ProofIdSentinel = std::numeric_limits<ProofId>::max(); + +typedef size_t AssertionOrder; +static AssertionOrder AssertionOrderSentinel = std::numeric_limits<AssertionOrder>::max(); + +/** + * A ValueCollection binds together convex constraints that have the same + * DeltaRational value. + */ +class ValueCollection { +private: + + Constraint d_lowerBound; + Constraint d_upperBound; + Constraint d_equality; + Constraint d_disequality; + +public: + ValueCollection() + : d_lowerBound(NullConstraint), + d_upperBound(NullConstraint), + d_equality(NullConstraint), + d_disequality(NullConstraint) + {} + + static ValueCollection mkFromConstraint(Constraint c); + + bool hasLowerBound() const{ + return d_lowerBound != NullConstraint; + } + bool hasUpperBound() const{ + return d_upperBound != NullConstraint; + } + bool hasEquality() const{ + return d_equality != NullConstraint; + } + bool hasDisequality() const { + return d_disequality != NullConstraint; + } + + bool hasConstraintOfType(ConstraintType t) const; + + Constraint getLowerBound() const { + Assert(hasLowerBound()); + return d_lowerBound; + } + Constraint getUpperBound() const { + Assert(hasUpperBound()); + return d_upperBound; + } + Constraint getEquality() const { + Assert(hasEquality()); + return d_equality; + } + Constraint getDisequality() const { + Assert(hasDisequality()); + return d_disequality; + } + + Constraint getConstraintOfType(ConstraintType t) const; + + /** Returns true if any of the constraints are non-null. */ + bool empty() const; + + /** + * Remove the constraint of the type t from the collection. + * Returns true if the ValueCollection is now empty. + * If true is returned, d_value is now NULL. + */ + void remove(ConstraintType t); + + /** + * Adds a constraint to the set. + * The collection must not have a constraint of that type already. + */ + void add(Constraint c); + + void push_into(std::vector<Constraint>& vec) const; + + Constraint nonNull() const; + + ArithVar getVariable() const; + const DeltaRational& getValue() const; +}; + +/** + * A Map of ValueCollections sorted by the associated DeltaRational values. + * + * Discussion: + * While it is more natural to consider this a set, this cannot be a set as in + * sets the type of both iterator and const_iterator in sets are + * "constant iterators". We require iterators that dereference to + * ValueCollection&. + * + * See: + * http://gcc.gnu.org/onlinedocs/libstdc++/ext/lwg-defects.html#103 + */ +typedef std::map<DeltaRational, ValueCollection> SortedConstraintMap; +typedef SortedConstraintMap::iterator SortedConstraintMapIterator; +typedef SortedConstraintMap::const_iterator SortedConstraintMapConstIterator; + +/** A Pair associating a variables and a Sorted ConstraintSet. */ +struct PerVariableDatabase{ + ArithVar d_var; + SortedConstraintMap d_constraints; + + // x ? c_1, x ? c_2, x ? c_3, ... + // where ? is a non-empty subset of {lb, ub, eq} + // c_1 < c_2 < c_3 < ... + + PerVariableDatabase(ArithVar v) : d_var(v), d_constraints() {} + + bool empty() const { + return d_constraints.empty(); + } + + static bool IsEmpty(const PerVariableDatabase& p){ + return p.empty(); + } +}; + +class ConstraintValue { +private: + /** The ArithVar associated with the constraint. */ + const ArithVar d_variable; + + /** The type of the Constraint. */ + const ConstraintType d_type; + + /** The DeltaRational value with the constraint. */ + const DeltaRational d_value; + + /** A pointer to the associated database for the Constraint. */ + ConstraintDatabase * d_database; + + /** + * The node to be communicated with the TheoryEngine. + * + * This is not context dependent, but may be set once. + * + * This must be set if the constraint canbePropgated(). + * This must be set if the constraint assertedToTheTheory(). + * Otherwise, this may be null(). + */ + Node d_literal; + + /** Pointer to the negation of the Constraint. */ + Constraint d_negation; + + /** + * This is true if the associated node can be propagated. + * + * This should be enabled if the node has been preregistered. + * + * Sat Context Dependent. + * This is initially false. + */ + bool d_canBePropagated; + + /** + * This is the order the constraint was asserted to the theory. + * If this has been set, the node can be used in conflicts. + * If this is c.d_assertedOrder < d.d_assertedOrder, then c can be used in the + * explanation of d. + * + * This should be set after the literal is dequeued by Theory::get(). + * + * Sat Context Dependent. + * This is initially AssertionOrderSentinel. + */ + AssertionOrder d_assertionOrder; + + /** + * This points at the proof for the constraint in the current context. + * + * Sat Context Dependent. + * This is initially ProofIdSentinel. + */ + ProofId d_proof; + + /** + * True if the equality has been split. + * Only meaningful if ContraintType == Equality. + * + * User Context Dependent. + * This is initially false. + */ + bool d_split; + + /** + * Position in sorted constraint set for the variable. + * Unset if d_type is Disequality. + */ + SortedConstraintMapIterator d_variablePosition; + + friend class ConstraintDatabase; + + /** + * This begins construction of a minimal constraint. + * + * This should only be called by ConstraintDatabase. + * + * Because of circular dependencies a Constraint is not fully valid until + * initialize has been called on it. + */ + ConstraintValue(ArithVar x, ConstraintType t, const DeltaRational& v); + + /** + * Destructor for a constraint. + * This should only be called if safeToGarbageCollect() is true. + */ + ~ConstraintValue(); + + bool initialized() const; + + /** + * This initializes the fields that cannot be set in the constructor due to + * circular dependencies. + */ + void initialize(ConstraintDatabase* db, SortedConstraintMapIterator v, Constraint negation); + + class ProofCleanup { + public: + inline void operator()(Constraint* p){ + Constraint constraint = *p; + Assert(constraint->d_proof != ProofIdSentinel); + constraint->d_proof = ProofIdSentinel; + } + }; + + class CanBePropagatedCleanup { + public: + inline void operator()(Constraint* p){ + Constraint constraint = *p; + Assert(constraint->d_canBePropagated); + constraint->d_canBePropagated = false; + } + }; + + class AssertionOrderCleanup { + public: + inline void operator()(Constraint* p){ + Constraint constraint = *p; + Assert(constraint->assertedToTheTheory()); + constraint->d_assertionOrder = AssertionOrderSentinel; + Assert(!constraint->assertedToTheTheory()); + } + }; + + class SplitCleanup { + public: + inline void operator()(Constraint* p){ + Constraint constraint = *p; + Assert(constraint->d_split); + constraint->d_split = false; + } + }; + + /** Returns true if the node is safe to garbage collect. */ + bool safeToGarbageCollect() const; + + /** + * Returns true if the node correctly corresponds to the constraint that is + * being set. + */ + bool sanityChecking(Node n) const; + + /** Returns a reference to the map for d_variable. */ + SortedConstraintMap& constraintSet() const; + +public: + + ConstraintType getType() const { + return d_type; + } + + ArithVar getVariable() const { + return d_variable; + } + + const DeltaRational& getValue() const { + return d_value; + } + + Constraint getNegation() const { + return d_negation; + } + + bool isEquality() const{ + return d_type == Equality; + } + bool isDisequality() const{ + return d_type == Disequality; + } + bool isLowerBound() const{ + return d_type == LowerBound; + } + bool isUpperBound() const{ + return d_type == UpperBound; + } + + bool isSplit() const { + return d_split; + } + + /** + * Splits the node in the user context. + * Returns a lemma that is assumed to be true fro the rest of the user context. + * Constraint must be an equality or disequality. + */ + Node split(); + + bool canBePropagated() const { + return d_canBePropagated; + } + void setCanBePropagated(); + + /** + * Light wrapper for calling setCanBePropagated(), + * on this and this-d_negation. + */ + void setPreregistered(){ + setCanBePropagated(); + d_negation->setCanBePropagated(); + } + + bool assertedToTheTheory() const { + return d_assertionOrder < AssertionOrderSentinel; + } + + bool assertedBefore(AssertionOrder time) const { + return d_assertionOrder < time; + } + + + void setAssertedToTheTheory(); + + + bool hasLiteral() const { + return !d_literal.isNull(); + } + + void setLiteral(Node n); + + Node getLiteral() const { + Assert(hasLiteral()); + return d_literal; + } + + /** + * Set the node as selfExplaining(). + * The node must be assertedToTheTheory(). + */ + void selfExplaining(); + + /** Returns true if the node is selfExplaining.*/ + bool isSelfExplaining() const; + + /** + * Set the constraint to be a EqualityEngine proof. + */ + void setEqualityEngineProof(); + bool hasEqualityEngineProof() const; + + /** + * Returns a explanation of the constraint that is appropriate for conflicts. + * + * This is not appropraite for propagation! + * + * This is the minimum fringe of the implication tree s.t. + * every constraint is assertedToTheTheory() or hasEqualityEngineProof(). + */ + Node explainForConflict() const{ + return explainBefore(AssertionOrderSentinel); + } + + /** + * Writes an explanation of a constraint into the node builder. + * Pushes back an explanation that is acceptable to send to the sat solver. + * nb is assumed to be an AND. + * + * This is the minimum fringe of the implication tree s.t. + * every constraint is assertedToTheTheory() or hasEqualityEngineProof(). + * + * This is not appropraite for propagation! + * Use explainForPropagation() instead. + */ + void explainForConflict(NodeBuilder<>& nb) const{ + explainBefore(nb, AssertionOrderSentinel); + } + + /** Utility function built from explainForConflict. */ + static Node explainConflict(Constraint a, Constraint b); + static Node explainConflict(Constraint a, Constraint b, Constraint c); + + /** + * Returns an explanation of a propagation by the ConstraintDatabase. + * The constraint must have a proof. + * The constraint cannot be selfExplaining(). + * + * This is the minimum fringe of the implication tree (excluding the constraint itself) + * s.t. every constraint is assertedToTheTheory() or hasEqualityEngineProof(). + */ + Node explainForPropagation() const { + Assert(hasProof()); + Assert(!isSelfExplaining()); + return explainBefore(d_assertionOrder); + } + +private: + Node explainBefore(AssertionOrder order) const; + + /** + * Returns an explanation of that was assertedBefore(order). + * The constraint must have a proof. + * The constraint cannot be selfExplaining(). + * + * This is the minimum fringe of the implication tree + * s.t. every constraint is assertedBefore(order) or hasEqualityEngineProof(). + */ + void explainBefore(NodeBuilder<>& nb, AssertionOrder order) const; + +public: + bool hasProof() const { + return d_proof != ProofIdSentinel; + } + bool negationHasProof() const { + return d_negation->hasProof(); + } + + bool truthIsUnknown() const { + return !hasProof() && !negationHasProof(); + } + + bool isTrue() const { + return hasProof(); + } + + Constraint getCeiling(); + + Constraint getFloor(); + + + static Constraint makeNegation(ArithVar v, ConstraintType t, const DeltaRational& r); + + const ValueCollection& getValueCollection() const; + + + Constraint getStrictlyWeakerUpperBound(bool hasLiteral, bool mustBeAsserted) const; + Constraint getStrictlyWeakerLowerBound(bool hasLiteral, bool mustBeAsserted) const; + + /** + * Marks the node as having a proof a. + * Adds the node the database's propagation queue. + * + * Preconditions: + * canBePropagated() + * !assertedToTheTheory() + */ + void propagate(Constraint a); + void propagate(Constraint a, Constraint b); + void propagate(const std::vector<Constraint>& b); + /** + * The only restriction is that this is not known be true. + * This propgates if there is a node. + */ + void impliedBy(Constraint a); + void impliedBy(Constraint a, Constraint b); + void impliedBy(const std::vector<Constraint>& b); + + + /** The node must have a proof already and be eligible for propagation! */ + void propagate(); + +private: + /** + * Marks the node as having a proof and being selfExplaining. + * Neither the node nor its negation can have a proof. + * This is internal! + */ + void markAsTrue(); + /** + * Marks the node as having a proof a. + * This is safe if the node does not have + */ + void markAsTrue(Constraint a); + + void markAsTrue(Constraint a, Constraint b); + void markAsTrue(const std::vector<Constraint>& b); + +public: + + +private: + + void debugPrint() const; + + /** + * The proof of the node is empty. + * The proof must be a special proof. Either + * isSelfExplaining() or + * hasEqualityEngineProof() + */ + bool proofIsEmpty() const; + +}; /* class ConstraintValue */ + +std::ostream& operator<<(std::ostream& o, const ConstraintValue& c); +std::ostream& operator<<(std::ostream& o, const Constraint c); +std::ostream& operator<<(std::ostream& o, const ConstraintType t); +std::ostream& operator<<(std::ostream& o, const ValueCollection& c); + + + +class ConstraintDatabase { +private: + /** + * The map from ArithVars to their unique databases. + * When the vector changes size, we cannot allow the maps to move so this + * is a vector of pointers. + */ + std::vector<PerVariableDatabase*> d_varDatabases; + + SortedConstraintMap& getVariableSCM(ArithVar v) const{ + Assert(variableDatabaseIsSetup(v)); + return d_varDatabases[v]->d_constraints; + } + + /** Maps literals to constraints.*/ + NodetoConstraintMap d_nodetoConstraintMap; + + /** + * A queue of propagated constraints. + * + * As Constraint are pointers, the elements of the queue do not require destruction. + */ + context::CDQueue<Constraint> d_toPropagate; + + /** + * Proof Lists. + * Proofs are lists of valid constraints terminated by the first smaller + * sentinel value in the proof list. + * The proof at p in d_proofs[p] of length n is + * (NullConstraint, d_proofs[p-(n-1)], ... , d_proofs[p-1], d_proofs[p]) + * The proof at p corresponds to the conjunction: + * (and x_i) + * + * So the proof of a Constraint c corresponds to the horn clause: + * (implies (and x_i) c) + * where (and x_i) is the proof at c.d_proofs. + * + * Constraints are pointers so this list is designed not to require any + * destruction. + */ + CDConstraintList d_proofs; + + /** + * This is a special proof for marking that nodes are their own explanation + * from the perspective of the theory. + * These must always be asserted to the theory. + * + * This proof is always a member of the list. + */ + ProofId d_selfExplainingProof; + + /** + * Marks a node as being proved by the equality engine. + * The equality engine will be asked for the explanation of such nodes. + * + * This is a special proof that is always a member of the list. + */ + ProofId d_equalityEngineProof; + + typedef context::CDList<Constraint, ConstraintValue::ProofCleanup> ProofCleanupList; + typedef context::CDList<Constraint, ConstraintValue::CanBePropagatedCleanup> CBPList; + typedef context::CDList<Constraint, ConstraintValue::AssertionOrderCleanup> AOList; + typedef context::CDList<Constraint, ConstraintValue::SplitCleanup> SplitList; + + /** + * The watch lists are collected together as they need to be garbage collected + * carefully. + */ + struct Watches{ + /** + * Contains the exact list of atoms that have a proof. + */ + ProofCleanupList d_proofWatches; + + /** + * Contains the exact list of constraints that can be used for propagation. + */ + CBPList d_canBePropagatedWatches; + + /** + * Contains the exact list of constraints that have been asserted to the theory. + */ + AOList d_assertionOrderWatches; + + + /** + * Contains the exact list of atoms that have been preregistered. + * This is a pointer as it must be destroyed before the elements of + * d_varDatabases. + */ + SplitList d_splitWatches; + Watches(context::Context* satContext, context::Context* userContext); + }; + Watches* d_watches; + + void pushSplitWatch(Constraint c){ + Assert(!c->d_split); + c->d_split = true; + d_watches->d_splitWatches.push_back(c); + } + + void pushCanBePropagatedWatch(Constraint c){ + Assert(!c->d_canBePropagated); + c->d_canBePropagated = true; + d_watches->d_canBePropagatedWatches.push_back(c); + } + + void pushAssertionOrderWatch(Constraint c){ + Assert(!c->assertedToTheTheory()); + c->d_assertionOrder = d_watches->d_assertionOrderWatches.size(); + d_watches->d_assertionOrderWatches.push_back(c); + } + + void pushProofWatch(Constraint c, ProofId pid){ + Assert(c->d_proof == ProofIdSentinel); + c->d_proof = pid; + d_watches->d_proofWatches.push_back(c); + } + + /** Returns true if all of the entries of the vector are empty. */ + static bool emptyDatabase(const std::vector<PerVariableDatabase>& vec); + + /** Map from nodes to arithvars. */ + const ArithVarNodeMap& d_av2nodeMap; + + const ArithVarNodeMap& getArithVarNodeMap() const{ + return d_av2nodeMap; + } + + DifferenceManager& d_differenceManager; + + //Constraint allocateConstraintForLiteral(ArithVar v, Node literal); + + const context::Context * const d_satContext; + const int d_satAllocationLevel; + + friend class ConstraintValue; + +public: + + ConstraintDatabase( context::Context* satContext, + context::Context* userContext, + const ArithVarNodeMap& av2nodeMap, + DifferenceManager& dm); + + ~ConstraintDatabase(); + + Constraint addLiteral(TNode lit); + //Constraint addAtom(TNode atom); + + /** + * If hasLiteral() is true, returns the constraint. + * Otherwise, returns NullConstraint. + */ + Constraint lookup(TNode literal) const; + + /** + * Returns true if the literal has been added to the database. + * This is a hash table lookup. + * It does not look in the database for an equivalent corresponding constraint. + */ + bool hasLiteral(TNode literal) const; + + bool hasMorePropagations() const{ + return !d_toPropagate.empty(); + } + + Constraint nextPropagation(){ + Assert(hasMorePropagations()); + + Constraint p = d_toPropagate.front(); + d_toPropagate.pop(); + + return p; + } + + void addVariable(ArithVar v); + bool variableDatabaseIsSetup(ArithVar v) const; + + Node eeExplain(ConstConstraint c) const; + void eeExplain(ConstConstraint c, NodeBuilder<>& nb) const; + + /** + * Returns a constraint with the variable v, the constraint type t, and a value + * dominated by r (explained below) if such a constraint exists in the database. + * If no such constraint exists, NullConstraint is returned. + * + * t must be either UpperBound or LowerBound. + * The returned value v is dominatated: + * If t is UpperBound, r <= v + * If t is LowerBound, r >= v + */ + Constraint getBestImpliedBound(ArithVar v, ConstraintType t, const DeltaRational& r) const; + + /** + * Returns a constraint with the variable v, the constraint type t and the value r. + * If there is such a constraint in the database already, it is returned. + * If there is no such constraint, this constraint is added to the database. + * + */ + Constraint getConstraint(ArithVar v, ConstraintType t, const DeltaRational& r); + + + /** + * Outputs a minimal set of unate implications on the output channel + * for all variables. + */ + void outputAllUnateLemmas(std::vector<Node>& lemmas) const; + + void outputAllUnateLemmas(std::vector<Node>& lemmas, ArithVar v) const; + +}; /* ConstraintDatabase */ + +}/* CVC4::theory::arith namespace */ +}/* CVC4::theory namespace */ +}/* CVC4 namespace */ + +#endif /* __CVC4__THEORY__ARITH__CONSTRAINT_H */ diff --git a/src/theory/arith/constraint_forward.h b/src/theory/arith/constraint_forward.h new file mode 100644 index 000000000..dd0c1f2f6 --- /dev/null +++ b/src/theory/arith/constraint_forward.h @@ -0,0 +1,42 @@ +/********************* */ +/*! \file constraint_forward.h + ** \verbatim + ** Original author: taking + ** Major contributors: none + ** Minor contributors (to current version): none + ** This file is part of the CVC4 prototype. + ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) + ** Courant Institute of Mathematical Sciences + ** New York University + ** See the file COPYING in the top-level source directory for licensing + ** information.\endverbatim + ** + ** \brief Forward declarations of the ConstraintValue and ConstraintDatabase classes. + ** + ** This is the forward declarations of the ConstraintValue and ConstraintDatabase + ** and the typedef for Constraint. This is used to break circular dependencies and + ** minimize interaction between header files. + **/ + +#include "cvc4_private.h" + +#ifndef __CVC4__THEORY__ARITH__CONSTRAINT_FORWARD_H +#define __CVC4__THEORY__ARITH__CONSTRAINT_FORWARD_H + +namespace CVC4 { +namespace theory { +namespace arith { + +class ConstraintValue; +typedef ConstraintValue* Constraint; +typedef const ConstraintValue* const ConstConstraint; + +static const Constraint NullConstraint = NULL; + +class ConstraintDatabase; + +}/* CVC4::theory::arith namespace */ +}/* CVC4::theory namespace */ +}/* CVC4 namespace */ + +#endif /* __CVC4__THEORY__ARITH__CONSTRAINT_FORWARD_H */ diff --git a/src/theory/arith/delta_rational.h b/src/theory/arith/delta_rational.h index a46dde1cf..12110fab4 100644 --- a/src/theory/arith/delta_rational.h +++ b/src/theory/arith/delta_rational.h @@ -55,14 +55,18 @@ public: } int sgn() const { - int x = getNoninfinitesimalPart().sgn(); - if(x == 0){ - return getInfinitesimalPart().sgn(); + int s = getNoninfinitesimalPart().sgn(); + if(s == 0){ + return infinitesimalSgn(); }else{ - return x; + return s; } } + int infinitesimalSgn() const { + return getInfinitesimalPart().sgn(); + } + int cmp(const DeltaRational& other) const{ int cmp = c.cmp(other.c); if(cmp == 0){ diff --git a/src/theory/arith/difference_manager.cpp b/src/theory/arith/difference_manager.cpp index b67240d4c..70588bc16 100644 --- a/src/theory/arith/difference_manager.cpp +++ b/src/theory/arith/difference_manager.cpp @@ -1,23 +1,131 @@ #include "theory/arith/difference_manager.h" #include "theory/uf/equality_engine_impl.h" +#include "theory/arith/constraint.h" +#include "theory/arith/arith_utilities.h" + namespace CVC4 { namespace theory { namespace arith { -DifferenceManager::DifferenceManager(context::Context* c, PropManager& pm) - : d_literalsQueue(c), - d_queue(pm), +DifferenceManager::DifferenceManager(context::Context* c, ConstraintDatabase& cd, TNodeCallBack& setup) + : d_conflict(c), + d_literalsQueue(c), + d_propagatations(c), + d_explanationMap(c), + d_constraintDatabase(cd), + d_setupLiteral(setup), d_notify(*this), d_ee(d_notify, c, "theory::arith::DifferenceManager"), d_false(NodeManager::currentNM()->mkConst<bool>(false)), d_hasSharedTerms(c, false) {} -void DifferenceManager::propagate(TNode x){ +void DifferenceManager::differenceIsZero(Constraint lb, Constraint ub){ + Assert(lb->isLowerBound()); + Assert(ub->isUpperBound()); + Assert(lb->getVariable() == ub->getVariable()); + Assert(lb->getValue().sgn() == 0); + Assert(ub->getValue().sgn() == 0); + + ArithVar s = lb->getVariable(); + Node reason = ConstraintValue::explainConflict(lb,ub); + + assertLiteral(true, s, reason); +} + +void DifferenceManager::differenceIsZero(Constraint eq){ + Assert(eq->isEquality()); + Assert(eq->getValue().sgn() == 0); + + ArithVar s = eq->getVariable(); + + //Explain for conflict is correct as these proofs are generated and stored eagerly + //These will be safe for propagation later as well + Node reason = eq->explainForConflict(); + + assertLiteral(true, s, reason); +} + +void DifferenceManager::differenceCannotBeZero(Constraint c){ + ArithVar s = c->getVariable(); + + //Explain for conflict is correct as these proofs are generated and stored eagerly + //These will be safe for propagation later as well + Node reason = c->explainForConflict(); + assertLiteral(false, s, reason); +} + + +bool DifferenceManager::propagate(TNode x){ Debug("arith::differenceManager")<< "DifferenceManager::propagate("<<x<<")"<<std::endl; + if(inConflict()){ + return true; + } + + Node rewritten = Rewriter::rewrite(x); + + //Need to still propagate this! + if(rewritten.getKind() == kind::CONST_BOOLEAN){ + pushBack(x); + } - d_queue.propagate(x, explain(x), true); + Assert(rewritten.getKind() != kind::CONST_BOOLEAN); + + Constraint c = d_constraintDatabase.lookup(rewritten); + if(c == NullConstraint){ + //using setup as there may not be a corresponding difference literal yet + d_setupLiteral(rewritten); + c = d_constraintDatabase.lookup(rewritten); + Assert(c != NullConstraint); + //c = d_constraintDatabase.addLiteral(rewritten); + } + + Debug("arith::differenceManager")<< "x is " + << c->hasProof() << " " + << (x == rewritten) << " " + << c->canBePropagated() << " " + << c->negationHasProof() << std::endl; + + if(c->negationHasProof()){ + Node expC = explainInternal(x); + Node neg = c->getNegation()->explainForConflict(); + Node conf = expC.andNode(neg); + Node final = flattenAnd(conf); + + d_conflict.set(final); + Debug("arith::differenceManager") << "differenceManager found a conflict " << final << std::endl; + return false; + } + + // Cases for propagation + // C : c has a proof + // S : x == rewritten + // P : c can be propagated + // + // CSP + // 000 : propagate x, and mark C it as being explained + // 001 : propagate x, and propagate c after marking it as being explained + // 01* : propagate x, mark c but do not propagate c + // 10* : propagate x, do not mark c and do not propagate c + // 11* : drop the constraint, do not propagate x or c + + if(!c->hasProof() && x != rewritten){ + pushBack(x, rewritten); + + c->setEqualityEngineProof(); + if(c->canBePropagated() && !c->assertedToTheTheory()){ + c->propagate(); + } + }else if(!c->hasProof() && x == rewritten){ + pushBack(x, rewritten); + c->setEqualityEngineProof(); + }else if(c->hasProof() && x != rewritten){ + pushBack(x, rewritten); + }else{ + Assert(c->hasProof() && x == rewritten); + } + return true; } void DifferenceManager::explain(TNode literal, std::vector<TNode>& assumptions) { @@ -37,33 +145,44 @@ void DifferenceManager::explain(TNode literal, std::vector<TNode>& assumptions) d_ee.explainEquality(lhs, rhs, assumptions); } -Node mkAnd(const std::vector<TNode>& conjunctions) { - Assert(conjunctions.size() > 0); +void DifferenceManager::enqueueIntoNB(const std::set<TNode> s, NodeBuilder<>& nb){ + std::set<TNode>::const_iterator it = s.begin(); + std::set<TNode>::const_iterator it_end = s.end(); + for(; it != it_end; ++it) { + nb << *it; + } +} - std::set<TNode> all; - all.insert(conjunctions.begin(), conjunctions.end()); +Node DifferenceManager::explainInternal(TNode internal){ + std::vector<TNode> assumptions; + explain(internal, assumptions); - if (all.size() == 1) { - // All the same, or just one - return conjunctions[0]; - } + std::set<TNode> assumptionSet; + assumptionSet.insert(assumptions.begin(), assumptions.end()); - NodeBuilder<> conjunction(kind::AND); - std::set<TNode>::const_iterator it = all.begin(); - std::set<TNode>::const_iterator it_end = all.end(); - while (it != it_end) { - conjunction << *it; - ++ it; + if (assumptionSet.size() == 1) { + // All the same, or just one + return assumptions[0]; + }else{ + NodeBuilder<> conjunction(kind::AND); + enqueueIntoNB(assumptionSet, conjunction); + return conjunction; } - - return conjunction; +} +Node DifferenceManager::explain(TNode external){ + Node internal = externalToInternal(external); + return explainInternal(internal); } +void DifferenceManager::explain(TNode external, NodeBuilder<>& out){ + Node internal = externalToInternal(external); -Node DifferenceManager::explain(TNode lit){ std::vector<TNode> assumptions; - explain(lit, assumptions); - return mkAnd(assumptions); + explain(internal, assumptions); + std::set<TNode> assumptionSet; + assumptionSet.insert(assumptions.begin(), assumptions.end()); + + enqueueIntoNB(assumptionSet, out); } void DifferenceManager::addDifference(ArithVar s, Node x, Node y){ @@ -90,7 +209,7 @@ void DifferenceManager::addAssertionToEqualityEngine(bool eq, ArithVar s, TNode void DifferenceManager::dequeueLiterals(){ Assert(d_hasSharedTerms); - while(!d_literalsQueue.empty()){ + while(!d_literalsQueue.empty() && !inConflict()){ const LiteralsQueueElem& front = d_literalsQueue.front(); d_literalsQueue.dequeue(); diff --git a/src/theory/arith/difference_manager.h b/src/theory/arith/difference_manager.h index c6e7f314d..7862a6b31 100644 --- a/src/theory/arith/difference_manager.h +++ b/src/theory/arith/difference_manager.h @@ -6,20 +6,52 @@ #define __CVC4__THEORY__ARITH__DIFFERENCE_MANAGER_H #include "theory/arith/arithvar.h" +#include "theory/arith/constraint_forward.h" #include "theory/uf/equality_engine.h" #include "context/cdo.h" #include "context/cdlist.h" #include "context/context.h" #include "context/cdtrail_queue.h" #include "util/stats.h" -#include "theory/arith/arith_prop_manager.h" namespace CVC4 { namespace theory { namespace arith { +/** + * This implements a CDMaybe. + * This has either been set in the context or it has not. + * T must have a default constructor and support assignment. + */ +template <class T> +class CDMaybe { +private: + typedef std::pair<bool, T> BoolTPair; + context::CDO<BoolTPair> d_data; + +public: + CDMaybe(context::Context* c) : d_data(c, std::make_pair(false, T())) + {} + + bool isSet() const { + return d_data.get().first; + } + + void set(const T& d){ + Assert(!isSet()); + d_data.set(std::make_pair(true, d)); + } + + const T& get() const{ + Assert(isSet()); + return d_data.get().second; + } +}; + class DifferenceManager { private: + CDMaybe<Node> d_conflict; + struct Difference { bool isSlack; TNode x; @@ -40,8 +72,7 @@ private: bool notify(TNode propagation) { Debug("arith::differences") << "DifferenceNotifyClass::notify(" << propagation << ")" << std::endl; // Just forward to dm - d_dm.propagate(propagation); - return true; + return d_dm.propagate(propagation); } void notify(TNode t1, TNode t2) { @@ -63,13 +94,69 @@ private: /** Stores the queue of assertions. This keeps the Node backing the reasons */ context::CDTrailQueue<LiteralsQueueElem> d_literalsQueue; - PropManager& d_queue; + //PropManager& d_queue; + + /** Store the propagations. */ + context::CDTrailQueue<Node> d_propagatations; + + /* This maps the node a theory engine will request on an explain call to + * to its corresponding PropUnit. + * This is node is potentially both the propagation or Rewriter::rewrite(propagation). + */ + typedef context::CDHashMap<Node, size_t, NodeHashFunction> ExplainMap; + ExplainMap d_explanationMap; + + ConstraintDatabase& d_constraintDatabase; + TNodeCallBack& d_setupLiteral; + +public: + + bool inConflict() const{ + return d_conflict.isSet(); + }; + Node conflict() const{ + Assert(inConflict()); + return d_conflict.get(); + } + + bool hasMorePropagations() const { + return !d_propagatations.empty(); + } + + const Node getNextPropagation() { + Assert(hasMorePropagations()); + Node prop = d_propagatations.front(); + d_propagatations.dequeue(); + return prop; + } + + bool canExplain(TNode n) const { + return d_explanationMap.find(n) != d_explanationMap.end(); + } + +private: + Node externalToInternal(TNode n) const{ + Assert(canExplain(n)); + size_t pos = (*(d_explanationMap.find(n))).second; + return d_propagatations[pos]; + } + + void pushBack(TNode n){ + d_explanationMap.insert(n, d_propagatations.size()); + d_propagatations.enqueue(n); + } + + void pushBack(TNode n, TNode r){ + d_explanationMap.insert(r, d_propagatations.size()); + d_explanationMap.insert(n, d_propagatations.size()); + d_propagatations.enqueue(n); + } DifferenceNotifyClass d_notify; theory::uf::EqualityEngine<DifferenceNotifyClass> d_ee; - void propagate(TNode x); + bool propagate(TNode x); void explain(TNode literal, std::vector<TNode>& assumptions); Node d_false; @@ -96,11 +183,16 @@ private: void enableSharedTerms(); void dequeueLiterals(); + void enqueueIntoNB(const std::set<TNode> all, NodeBuilder<>& nb); + + Node explainInternal(TNode internal); + public: - DifferenceManager(context::Context*, PropManager&); + DifferenceManager(context::Context* satContext, ConstraintDatabase&, TNodeCallBack&); Node explain(TNode literal); + void explain(TNode lit, NodeBuilder<>& out); void addDifference(ArithVar s, Node x, Node y); @@ -112,13 +204,14 @@ public: } } - void differenceIsZero(ArithVar s, TNode reason){ - assertLiteral(true, s, reason); - } + /** Assert an equality. */ + void differenceIsZero(Constraint eq); - void differenceCannotBeZero(ArithVar s, TNode reason){ - assertLiteral(false, s, reason); - } + /** Assert a conjunction from lb and ub. */ + void differenceIsZero(Constraint lb, Constraint ub); + + /** Assert that the value cannot be zero. */ + void differenceCannotBeZero(Constraint c); void addSharedTerm(Node x); };/* class DifferenceManager */ diff --git a/src/theory/arith/dio_solver.cpp b/src/theory/arith/dio_solver.cpp index 1e47d6cdd..1b3a5cac7 100644 --- a/src/theory/arith/dio_solver.cpp +++ b/src/theory/arith/dio_solver.cpp @@ -76,6 +76,22 @@ DioSolver::Statistics::~Statistics(){ StatisticsRegistry::unregisterStat(&d_cutTimer); } +bool DioSolver::queueConditions(TrailIndex t){ + /* debugPrintTrail(t); */ + Debug("queueConditions") << !inConflict() << std::endl; + Debug("queueConditions") << gcdIsOne(t) << std::endl; + Debug("queueConditions") << !debugAnySubstitionApplies(t) << std::endl; + Debug("queueConditions") << !triviallySat(t) << std::endl; + Debug("queueConditions") << !triviallyUnsat(t) << std::endl; + + return + !inConflict() && + gcdIsOne(t) && + !debugAnySubstitionApplies(t) && + !triviallySat(t) && + !triviallyUnsat(t); +} + size_t DioSolver::allocateVariableInPool() { Assert(d_lastUsedVariable <= d_variablePool.size()); if(d_lastUsedVariable == d_variablePool.size()){ @@ -125,9 +141,10 @@ bool DioSolver::acceptableOriginalNodes(Node n){ }else if(k == kind::AND){ Node ub = n[0]; Node lb = n[1]; - Kind kub = simplifiedKind(ub); - Kind klb = simplifiedKind(lb); - return (kub == kind::LEQ || kub==kind::LT) && (klb == kind::GEQ || klb == kind::GT); + Kind kub = Comparison::comparisonKind(ub); + Kind klb = Comparison::comparisonKind(lb); + Debug("nf::tmp") << n << endl; + return (kub == kind::GEQ || kub==kind::LT) && (klb == kind::GEQ || klb == kind::LT); }else{ return false; } @@ -135,11 +152,11 @@ bool DioSolver::acceptableOriginalNodes(Node n){ void DioSolver::pushInputConstraint(const Comparison& eq, Node reason){ Assert(!debugEqualityInInputEquations(reason)); - Assert(eq.isIntegral()); + Assert(eq.debugIsIntegral()); Assert(eq.getNode().getKind() == kind::EQUAL); Assert(acceptableOriginalNodes(reason)); - SumPair sp = SumPair::comparisonToSumPair(eq); + SumPair sp = eq.toSumPair(); uint32_t length = sp.maxLength(); if(length > d_maxInputCoefficientLength){ d_maxInputCoefficientLength = length; @@ -573,7 +590,6 @@ DioSolver::TrailIndex DioSolver::applyAllSubstitutionsToIndex(DioSolver::TrailIn bool DioSolver::debugSubstitutionApplies(DioSolver::SubIndex si, DioSolver::TrailIndex ti){ Variable var = d_subs[si].d_eliminated; - TrailIndex subIndex = d_subs[si].d_constraint; const SumPair& curr = d_trail[ti].d_eq; Polynomial vsum = curr.getPolynomial(); diff --git a/src/theory/arith/dio_solver.h b/src/theory/arith/dio_solver.h index 677040615..c5a0f534f 100644 --- a/src/theory/arith/dio_solver.h +++ b/src/theory/arith/dio_solver.h @@ -338,22 +338,8 @@ private: /** Returns true if the queue of nodes to process is empty. */ bool queueEmpty() const; - bool queueConditions(TrailIndex t){ - /* debugPrintTrail(t); */ - - /* std::cout << !inConflict() << std::endl; */ - /* std::cout << gcdIsOne(t) << std::endl; */ - /* std::cout << !debugAnySubstitionApplies(t) << std::endl; */ - /* std::cout << !triviallySat(t) << std::endl; */ - /* std::cout << !triviallyUnsat(t) << std::endl; */ - - return - !inConflict() && - gcdIsOne(t) && - !debugAnySubstitionApplies(t) && - !triviallySat(t) && - !triviallyUnsat(t); - } + bool queueConditions(TrailIndex t); + void pushToQueueBack(TrailIndex t){ Assert(queueConditions(t)); diff --git a/src/theory/arith/linear_equality.cpp b/src/theory/arith/linear_equality.cpp index c84e61285..ca7cd69c4 100644 --- a/src/theory/arith/linear_equality.cpp +++ b/src/theory/arith/linear_equality.cpp @@ -26,8 +26,8 @@ namespace theory { namespace arith { /* Explicitly instatiate this function. */ -template void LinearEqualityModule::explainNonbasics<true>(ArithVar basic, NodeBuilder<>& output); -template void LinearEqualityModule::explainNonbasics<false>(ArithVar basic, NodeBuilder<>& output); +template void LinearEqualityModule::propagateNonbasics<true>(ArithVar basic, Constraint c); +template void LinearEqualityModule::propagateNonbasics<false>(ArithVar basic, Constraint c); LinearEqualityModule::Statistics::Statistics(): d_statPivots("theory::arith::pivots",0), @@ -71,7 +71,7 @@ void LinearEqualityModule::update(ArithVar x_i, const DeltaRational& v){ DeltaRational nAssignment = assignment+(diff * a_ji); d_partialModel.setAssignment(x_j, nAssignment); - d_basicVariableUpdates.callback(x_j); + d_basicVariableUpdates(x_j); } d_partialModel.setAssignment(x_i, v); @@ -119,7 +119,7 @@ void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, DeltaRatio DeltaRational nextAssignment = d_partialModel.getAssignment(x_k) + (theta * a_kj); d_partialModel.setAssignment(x_k, nextAssignment); - d_basicVariableUpdates.callback(x_k); + d_basicVariableUpdates(x_k); } } @@ -131,7 +131,7 @@ void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, DeltaRatio //(d_statistics.d_avgNumRowsNotContainingOnPivot).addEntry(difference); d_tableau.pivot(x_i, x_j); - d_basicVariableUpdates.callback(x_j); + d_basicVariableUpdates(x_j); if(Debug.isOn("tableau")){ d_tableau.printTableau(); @@ -255,12 +255,17 @@ bool LinearEqualityModule::hasBounds(ArithVar basic, bool upperBound){ } template <bool upperBound> -void LinearEqualityModule::explainNonbasics(ArithVar basic, NodeBuilder<>& output){ +void LinearEqualityModule::propagateNonbasics(ArithVar basic, Constraint c){ Assert(d_tableau.isBasic(basic)); + Assert(c->getVariable() == basic); + Assert(!c->assertedToTheTheory()); + Assert(c->canBePropagated()); + Assert(!c->hasProof()); Debug("arith::explainNonbasics") << "LinearEqualityModule::explainNonbasics(" << basic <<") start" << endl; + vector<Constraint> bounds; Tableau::RowIterator iter = d_tableau.rowIterator(basic); for(; !iter.atEnd(); ++iter){ @@ -269,30 +274,42 @@ void LinearEqualityModule::explainNonbasics(ArithVar basic, NodeBuilder<>& outpu if(nonbasic == basic) continue; const Rational& a_ij = entry.getCoefficient(); - TNode bound = TNode::null(); int sgn = a_ij.sgn(); Assert(sgn != 0); + Constraint bound = NullConstraint; if(upperBound){ if(sgn < 0){ - bound = d_partialModel.getLowerConstraint(nonbasic); + bound = d_partialModel.getLowerBoundConstraint(nonbasic); + //d_partialModel.explainLowerBound(nonbasic, output); + //bound = d_partialModel.explainLowerBound(nonbasic); }else{ Assert(sgn > 0); - bound = d_partialModel.getUpperConstraint(nonbasic); + bound = d_partialModel.getUpperBoundConstraint(nonbasic); + //d_partialModel.explainUpperBound(nonbasic, output); + //bound = d_partialModel.explainUpperBound(nonbasic); } }else{ if(sgn < 0){ - bound = d_partialModel.getUpperConstraint(nonbasic); + bound = d_partialModel.getUpperBoundConstraint(nonbasic); + //d_partialModel.explainUpperBound(nonbasic, output); + //bound = d_partialModel.explainUpperBound(nonbasic); }else{ Assert(sgn > 0); - bound = d_partialModel.getLowerConstraint(nonbasic); + bound = d_partialModel.getLowerBoundConstraint(nonbasic); + //d_partialModel.explainLowerBound(nonbasic, output); + //bound = d_partialModel.explainLowerBound(nonbasic); } } - Assert(!bound.isNull()); - Debug("arith::explainNonbasics") << "\t" << nonbasic << " " << sgn << " " << bound - << endl; - output << bound; + Assert(bound != NullConstraint); + Debug("arith::explainNonbasics") << "explainNonbasics" << bound << " for " << c << endl; + bounds.push_back(bound); + //Assert(!bound.isNull()); + // Debug("arith::explainNonbasics") << "\t" << nonbasic << " " << sgn << " " << bound + // << endl; + // output << bound; } + c->propagate(bounds); Debug("arith::explainNonbasics") << "LinearEqualityModule::explainNonbasics(" << basic << ") done" << endl; } diff --git a/src/theory/arith/linear_equality.h b/src/theory/arith/linear_equality.h index 4d1d917b3..b5d439769 100644 --- a/src/theory/arith/linear_equality.h +++ b/src/theory/arith/linear_equality.h @@ -36,6 +36,7 @@ #include "theory/arith/arithvar.h" #include "theory/arith/partial_model.h" #include "theory/arith/tableau.h" +#include "theory/arith/constraint.h" #include "util/stats.h" @@ -101,14 +102,16 @@ private: * of the basic variable basic, using the non-basic variables in the row. */ template <bool upperBound> - void explainNonbasics(ArithVar basic, NodeBuilder<>& output); + void propagateNonbasics(ArithVar basic, Constraint c); public: - void explainNonbasicsLowerBound(ArithVar basic, NodeBuilder<>& output){ - explainNonbasics<false>(basic, output); + void propagateNonbasicsLowerBound(ArithVar basic, Constraint c){ + Assert(c->isLowerBound()); + propagateNonbasics<false>(basic, c); } - void explainNonbasicsUpperBound(ArithVar basic, NodeBuilder<>& output){ - explainNonbasics<true>(basic, output); + void propagateNonbasicsUpperBound(ArithVar basic, Constraint c){ + Assert(c->isUpperBound()); + propagateNonbasics<true>(basic, c); } /** diff --git a/src/theory/arith/normal_form.cpp b/src/theory/arith/normal_form.cpp index 31cd8cd70..6f8a46236 100644 --- a/src/theory/arith/normal_form.cpp +++ b/src/theory/arith/normal_form.cpp @@ -18,6 +18,7 @@ **/ #include "theory/arith/normal_form.h" +#include "theory/arith/arith_utilities.h" #include <list> using namespace std; @@ -122,15 +123,25 @@ Monomial Monomial::parseMonomial(Node n) { return Monomial(VarList::parseVarList(n)); } } -Monomial Monomial::operator*(const Constant& c) const { - if(c.isZero()){ +Monomial Monomial::operator*(const Rational& q) const { + if(q.isZero()){ return mkZero(); }else{ - Constant newConstant = this->getConstant() * c; + Constant newConstant = this->getConstant() * q; return Monomial::mkMonomial(newConstant, getVarList()); } } +Monomial Monomial::operator*(const Constant& c) const { + return (*this) * c.getValue(); + // if(c.isZero()){ + // return mkZero(); + // }else{ + // Constant newConstant = this->getConstant() * c; + // return Monomial::mkMonomial(newConstant, getVarList()); + // } +} + Monomial Monomial::operator*(const Monomial& mono) const { Constant newConstant = this->getConstant() * mono.getConstant(); VarList newVL = this->getVarList() * mono.getVarList(); @@ -188,15 +199,15 @@ Polynomial Polynomial::operator-(const Polynomial& vl) const { return *this + (vl*negOne); } -Polynomial Polynomial::operator*(const Constant& c) const{ - if(c.isZero()){ +Polynomial Polynomial::operator*(const Rational& q) const{ + if(q.isZero()){ return Polynomial::mkZero(); - }else if(c.isOne()){ + }else if(q.isOne()){ return *this; }else{ std::vector<Monomial> newMonos; for(iterator i = this->begin(), end = this->end(); i != end; ++i) { - newMonos.push_back((*i)*c); + newMonos.push_back((*i)*q); } Assert(Monomial::isStrictlySorted(newMonos)); @@ -204,6 +215,23 @@ Polynomial Polynomial::operator*(const Constant& c) const{ } } +Polynomial Polynomial::operator*(const Constant& c) const{ + return (*this) * c.getValue(); + // if(c.isZero()){ + // return Polynomial::mkZero(); + // }else if(c.isOne()){ + // return *this; + // }else{ + // std::vector<Monomial> newMonos; + // for(iterator i = this->begin(), end = this->end(); i != end; ++i) { + // newMonos.push_back((*i)*c); + // } + + // Assert(Monomial::isStrictlySorted(newMonos)); + // return Polynomial::mkPolynomial(newMonos); + // } +} + Polynomial Polynomial::operator*(const Monomial& mono) const { if(mono.isZero()) { return Polynomial(mono); //Don't multiply by zero @@ -248,10 +276,29 @@ Monomial Polynomial::selectAbsMinimum() const { return min; } +bool Polynomial::leadingCoefficientIsAbsOne() const { + return getHead().absCoefficientIsOne(); +} +bool Polynomial::leadingCoefficientIsPositive() const { + return getHead().getConstant().isPositive(); +} + +bool Polynomial::denominatorLCMIsOne() const { + return denominatorLCM().isOne(); +} + +bool Polynomial::numeratorGCDIsOne() const { + return gcd().isOne(); +} + Integer Polynomial::gcd() const { + Assert(isIntegral()); + return numeratorGCD(); +} + +Integer Polynomial::numeratorGCD() const { //We'll use the standardization that gcd(0, 0) = 0 //So that the gcd of the zero polynomial is gcd{0} = 0 - Assert(isIntegral()); iterator i=begin(), e=end(); Assert(i!=e); @@ -273,355 +320,918 @@ Integer Polynomial::denominatorLCM() const { return tmp; } + +Constant Polynomial::getCoefficient(const VarList& vl) const{ + //TODO improve to binary search... + for(iterator iter=begin(), myend=end(); iter != myend; ++iter){ + Monomial m = *iter; + VarList curr = m.getVarList(); + if(curr == vl){ + return m.getConstant(); + } + } + return Constant::mkConstant(0); +} + +Node Polynomial::computeQR(const Polynomial& p, const Integer& div){ + Assert(p.isIntegral()); + std::vector<Monomial> q_vec, r_vec; + Integer tmp_q, tmp_r; + for(iterator iter = p.begin(), pend = p.end(); iter != pend; ++iter){ + Monomial curr = *iter; + VarList vl = curr.getVarList(); + Constant c = curr.getConstant(); + + const Integer& a = c.getValue().getNumerator(); + Integer::floorQR(tmp_q, tmp_r, a, div); + Constant q=Constant::mkConstant(tmp_q); + Constant r=Constant::mkConstant(tmp_r); + if(!q.isZero()){ + q_vec.push_back(Monomial::mkMonomial(q, vl)); + } + if(!r.isZero()){ + r_vec.push_back(Monomial::mkMonomial(r, vl)); + } + } + + Polynomial p_q = Polynomial::mkPolynomial(q_vec); + Polynomial p_r = Polynomial::mkPolynomial(r_vec); + + return NodeManager::currentNM()->mkNode(kind::PLUS, p_q.getNode(), p_r.getNode()); +} + + +Monomial Polynomial::minimumVariableMonomial() const{ + Assert(!isConstant()); + if(singleton()){ + return getHead(); + }else{ + iterator i = begin(); + Monomial first = *i; + if( first.isConstant() ){ + ++i; + Assert(i != end()); + return *i; + }else{ + return first; + } + } +} + +bool Polynomial::variableMonomialAreStrictlyGreater(const Monomial& m) const{ + if(isConstant()){ + return true; + }else{ + Monomial minimum = minimumVariableMonomial(); + Debug("nf::tmp") << "minimum " << minimum.getNode() << endl; + Debug("nf::tmp") << "m " << m.getNode() << endl; + return m < minimum; + } +} + +Node SumPair::computeQR(const SumPair& sp, const Integer& div){ + Assert(sp.isIntegral()); + + const Integer& constant = sp.getConstant().getValue().getNumerator(); + + Integer constant_q, constant_r; + Integer::floorQR(constant_q, constant_r, constant, div); + + Node p_qr = Polynomial::computeQR(sp.getPolynomial(), div); + Assert(p_qr.getKind() == kind::PLUS); + Assert(p_qr.getNumChildren() == 2); + + Polynomial p_q = Polynomial::parsePolynomial(p_qr[0]); + Polynomial p_r = Polynomial::parsePolynomial(p_qr[1]); + + SumPair sp_q(p_q, Constant::mkConstant(constant_q)); + SumPair sp_r(p_r, Constant::mkConstant(constant_r)); + + return NodeManager::currentNM()->mkNode(kind::PLUS, sp_q.getNode(), sp_r.getNode()); +} + +SumPair SumPair::mkSumPair(const Polynomial& p){ + if(p.isConstant()){ + Constant leadingConstant = p.getHead().getConstant(); + return SumPair(Polynomial::mkZero(), leadingConstant); + }else if(p.containsConstant()){ + Assert(!p.singleton()); + return SumPair(p.getTail(), p.getHead().getConstant()); + }else{ + return SumPair(p, Constant::mkZero()); + } +} + +Comparison::Comparison(TNode n) + : NodeWrapper(n) +{ + Assert(isNormalForm()); +} + + + +SumPair Comparison::toSumPair() const { + Kind cmpKind = comparisonKind(); + switch(cmpKind){ + case kind::LT: + case kind::LEQ: + case kind::GT: + case kind::GEQ: + { + TNode lit = getNode(); + TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit; + Polynomial p = Polynomial::parsePolynomial(atom[0]); + Constant c = Constant::mkConstant(atom[1]); + if(p.leadingCoefficientIsPositive()){ + return SumPair(p, -c); + }else{ + return SumPair(-p, c); + } + } + case kind::EQUAL: + case kind::DISTINCT: + { + Polynomial left = getLeft(); + Polynomial right = getRight(); + Debug("nf::tmp") << "left: " << left.getNode() << endl; + Debug("nf::tmp") << "right: " << right.getNode() << endl; + if(right.isConstant()){ + return SumPair(left, -right.getHead().getConstant()); + }else if(right.containsConstant()){ + Assert(!right.singleton()); + + Polynomial noConstant = right.getTail(); + return SumPair(left - noConstant, -right.getHead().getConstant()); + }else{ + return SumPair(left - right, Constant::mkZero()); + } + } + default: + Unhandled(cmpKind); + } +} + +Polynomial Comparison::normalizedVariablePart() const { + Kind cmpKind = comparisonKind(); + switch(cmpKind){ + case kind::LT: + case kind::LEQ: + case kind::GT: + case kind::GEQ: + { + TNode lit = getNode(); + TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit; + Polynomial p = Polynomial::parsePolynomial(atom[0]); + if(p.leadingCoefficientIsPositive()){ + return p; + }else{ + return -p; + } + } + case kind::EQUAL: + case kind::DISTINCT: + { + Polynomial left = getLeft(); + Polynomial right = getRight(); + if(right.isConstant()){ + return left; + }else if(right.containsConstant()){ + Polynomial noConstant = right.getTail(); + return left - noConstant; + }else{ + return left - right; + } + } + default: + Unhandled(cmpKind); + } +} + +DeltaRational Comparison::normalizedDeltaRational() const { + Kind cmpKind = comparisonKind(); + int delta = deltaCoeff(cmpKind); + switch(cmpKind){ + case kind::LT: + case kind::LEQ: + case kind::GT: + case kind::GEQ: + { + Node lit = getNode(); + Node atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit; + Polynomial left = Polynomial::parsePolynomial(atom[0]); + const Rational& q = atom[1].getConst<Rational>(); + if(left.leadingCoefficientIsPositive()){ + return DeltaRational(q, delta); + }else{ + return DeltaRational(-q, -delta); + } + } + case kind::EQUAL: + case kind::DISTINCT: + { + Monomial firstRight = getRight().getHead(); + if(firstRight.isConstant()){ + return DeltaRational(firstRight.getConstant().getValue(), 0); + }else{ + return DeltaRational(0, 0); + } + } + default: + Unhandled(cmpKind); + } +} + +Comparison Comparison::parseNormalForm(TNode n) { + Comparison result(n); + Assert(result.isNormalForm()); + return result; +} + Node Comparison::toNode(Kind k, const Polynomial& l, const Constant& r) { Assert(isRelationOperator(k)); switch(k) { case kind::GEQ: + case kind::GT: + return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode()); + default: + Unhandled(k); + } +} + +Node Comparison::toNode(Kind k, const Polynomial& l, const Polynomial& r) { + Assert(isRelationOperator(k)); + switch(k) { + case kind::GEQ: case kind::EQUAL: + case kind::GT: + return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode()); case kind::LEQ: - return NodeManager::currentNM()->mkNode(k, l.getNode(),r.getNode()); + return toNode(kind::GEQ, r, l).notNode(); case kind::LT: - return NodeManager::currentNM()->mkNode(kind::NOT, toNode(kind::GEQ,l,r)); - case kind::GT: - return NodeManager::currentNM()->mkNode(kind::NOT, toNode(kind::LEQ,l,r)); + return toNode(kind::GT, r, l).notNode(); + case kind::DISTINCT: + return toNode(kind::EQUAL, r, l).notNode(); default: Unreachable(); } } -Comparison Comparison::parseNormalForm(TNode n) { - if(n.getKind() == kind::CONST_BOOLEAN) { - return Comparison(n.getConst<bool>()); - } else { - bool negated = n.getKind() == kind::NOT; - Node relation = negated ? n[0] : n; - Assert( !negated || - relation.getKind() == kind::LEQ || - relation.getKind() == kind::GEQ); - - Polynomial left = Polynomial::parsePolynomial(relation[0]); - Constant right(relation[1]); - - Kind newOperator = relation.getKind(); - if(negated) { - if(newOperator == kind::LEQ) { - newOperator = kind::GT; - } else { - newOperator = kind::LT; - } - } - return Comparison(n, newOperator, left, right); +bool Comparison::rightIsConstant() const { + if(getNode().getKind() == kind::NOT){ + return getNode()[0][1].getKind() == kind::CONST_RATIONAL; + }else{ + return getNode()[1].getKind() == kind::CONST_RATIONAL; } } -bool Comparison::pbComparison(Kind k, TNode left, const Rational& right, bool& result) { - AssertArgument(left.getType().isPseudoboolean(), left); - switch(k) { +Polynomial Comparison::getLeft() const { + TNode left; + Kind k = comparisonKind(); + switch(k){ case kind::LT: - if(right > 1) { - result = true; - return true; - } else if(right <= 0) { - result = false; - return true; - } - break; case kind::LEQ: - if(right >= 1) { - result = true; - return true; - } else if(right < 0) { - result = false; - return true; - } + case kind::DISTINCT: + left = getNode()[0][0]; break; case kind::EQUAL: - if(right != 0 && right != 1) { - result = false; - return true; - } - break; + case kind::GT: case kind::GEQ: - if(right > 1) { - result = false; - return true; - } else if(right <= 0) { - result = true; - return true; - } + left = getNode()[0]; + break; + default: + Unhandled(k); + } + return Polynomial::parsePolynomial(left); +} + +Polynomial Comparison::getRight() const { + TNode right; + Kind k = comparisonKind(); + switch(k){ + case kind::LT: + case kind::LEQ: + case kind::DISTINCT: + right = getNode()[0][1]; break; + case kind::EQUAL: case kind::GT: - if(right >= 1) { - result = false; - return true; - } else if(right < 0) { - result = true; - return true; - } + case kind::GEQ: + right = getNode()[1]; break; default: - CheckArgument(false, k, "Bad comparison operator ?!"); + Unhandled(k); } - - return false; + return Polynomial::parsePolynomial(right); } -// Comparison Comparison::mkComparison(Kind k, const Polynomial& left, const Constant& right) { -// Assert(isRelationOperator(k)); -// if(left.isConstant()) { -// const Rational& lConst = left.getNode().getConst<Rational>(); -// const Rational& rConst = right.getNode().getConst<Rational>(); -// bool res = evaluateConstantPredicate(k, lConst, rConst); -// return Comparison(res); -// } - -// if(left.getNode().getType().isPseudoboolean()) { -// bool result; -// if(pbComparison(k, left.getNode(), right.getNode().getConst<Rational>(), result)) { -// return Comparison(result); -// } -// } +// Polynomial Comparison::getLeft() const { +// Node n = getNode(); +// Node left = (n.getKind() == kind::NOT ? n[0]: n)[0]; +// return Polynomial::parsePolynomial(left); +// } -// return Comparison(toNode(k, left, right), k, left, right); +// Polynomial Comparison::getRight() const { +// Node n = getNode(); +// Node right = (n.getKind() == kind::NOT ? n[0]: n)[1]; +// return Polynomial::parsePolynomial(right); // } -Comparison Comparison::mkComparison(Kind k, const Polynomial& left, const Constant& right) { - Assert(isRelationOperator(k)); - return Comparison(toNode(k, left, right), k, left, right); +bool Comparison::isNormalForm() const { + Node n = getNode(); + Kind cmpKind = comparisonKind(n); + Debug("nf::tmp") << "isNormalForm " << n << " " << cmpKind << endl; + switch(cmpKind){ + case kind::CONST_BOOLEAN: + return true; + case kind::GT: + return isNormalGT(); + case kind::GEQ: + return isNormalGEQ(); + case kind::EQUAL: + return isNormalEquality(); + case kind::LT: + return isNormalLT(); + case kind::LEQ: + return isNormalLEQ(); + case kind::DISTINCT: + return isNormalDistinct(); + default: + return false; + } } -Comparison Comparison::addConstant(const Constant& constant) const { - Assert(!isBoolean()); - Monomial mono(constant); - Polynomial constAsPoly( mono ); - Polynomial newLeft = getLeft() + constAsPoly; - Constant newRight = getRight() + constant; - return mkComparison(oper, newLeft, newRight); +/** This must be (> qpolynomial constant) */ +bool Comparison::isNormalGT() const { + Node n = getNode(); + Assert(n.getKind() == kind::GT); + if(!rightIsConstant()){ + return false; + }else{ + Polynomial left = getLeft(); + if(left.containsConstant()){ + return false; + }else if(!left.leadingCoefficientIsAbsOne()){ + return false; + }else{ + return !left.isIntegral(); + } + } } -bool Comparison::constantInLefthand() const{ - return getLeft().containsConstant(); +/** This must be (not (> qpolynomial constant)) */ +bool Comparison::isNormalLEQ() const { + Node n = getNode(); + Debug("nf::tmp") << "isNormalLEQ " << n << endl; + Assert(n.getKind() == kind::NOT); + Assert(n[0].getKind() == kind::GT); + if(!rightIsConstant()){ + return false; + }else{ + Polynomial left = getLeft(); + if(left.containsConstant()){ + return false; + }else if(!left.leadingCoefficientIsAbsOne()){ + return false; + }else{ + return !left.isIntegral(); + } + } } -Comparison Comparison::cancelLefthandConstant() const { - if(constantInLefthand()){ - Monomial constantHead = getLeft().getHead(); - Assert(constantHead.isConstant()); - Constant constant = constantHead.getConstant(); - Constant negativeConstantHead = -constant; - return addConstant(negativeConstantHead); +/** This must be (>= qpolynomial constant) or (>= zpolynomial constant) */ +bool Comparison::isNormalGEQ() const { + Node n = getNode(); + Assert(n.getKind() == kind::GEQ); + + Debug("nf::tmp") << "isNormalGEQ " << n << " " << rightIsConstant() << endl; + + if(!rightIsConstant()){ + return false; }else{ - return *this; + Polynomial left = getLeft(); + if(left.containsConstant()){ + return false; + }else{ + if(left.isIntegral()){ + return left.denominatorLCMIsOne() && left.numeratorGCDIsOne(); + }else{ + Debug("nf::tmp") << "imme sdfhkdjfh "<< left.leadingCoefficientIsAbsOne() << endl; + return left.leadingCoefficientIsAbsOne(); + } + } } } -Comparison Comparison::multiplyConstant(const Constant& constant) const { - Assert(!isBoolean()); - Kind newOper = (constant.getValue() < 0) ? reverseRelationKind(oper) : oper; +/** This must be (not (>= qpolynomial constant)) or (not (>= zpolynomial constant)) */ +bool Comparison::isNormalLT() const { + Node n = getNode(); + Assert(n.getKind() == kind::NOT); + Assert(n[0].getKind() == kind::GEQ); - return mkComparison(newOper, left*Monomial(constant), right*constant); + if(!rightIsConstant()){ + return false; + }else{ + Polynomial left = getLeft(); + if(left.containsConstant()){ + return false; + }else{ + if(left.isIntegral()){ + return left.denominatorLCMIsOne() && left.numeratorGCDIsOne(); + }else{ + return left.leadingCoefficientIsAbsOne(); + } + } + } } -Integer Comparison::denominatorLCM() const { - // Get the coefficients to be all integers. - Integer leftDenominatorLCM = left.denominatorLCM(); - Integer rightDenominator = right.getValue().getDenominator(); - Integer denominatorLCM = leftDenominatorLCM.lcm(rightDenominator); - Assert(denominatorLCM.sgn() > 0); - return denominatorLCM; -} -Comparison Comparison::multiplyByDenominatorLCM() const{ - return multiplyConstant(Constant::mkConstant(denominatorLCM())); -} +bool Comparison::isNormalEqualityOrDisequality() const { + Polynomial pleft = getLeft(); -Comparison Comparison::normalizeLeadingCoefficientPositive() const { - if(getLeft().getHead().getConstant().isNegative()){ - return multiplyConstant(Constant::mkConstant(-1)); + if(pleft.numMonomials() == 1){ + Monomial mleft = pleft.getHead(); + if(mleft.isConstant()){ + return false; + }else{ + Polynomial pright = getRight(); + if(allIntegralVariables()){ + const Rational& lcoeff = mleft.getConstant().getValue(); + if(pright.isConstant()){ + return pright.isIntegral() && lcoeff.isOne(); + } + Polynomial varRight = pright.containsConstant() ? pright.getTail() : pright; + if(lcoeff.sgn() <= 0){ + return false; + }else{ + Integer lcm = lcoeff.getDenominator().lcm(varRight.denominatorLCM()); + Integer g = lcoeff.getNumerator().gcd(varRight.numeratorGCD()); + Debug("nf::tmp") << lcm << " " << g << endl; + if(!lcm.isOne()){ + return false; + }else if(!g.isOne()){ + return false; + }else{ + Monomial absMinRight = varRight.selectAbsMinimum(); + Debug("nf::tmp") << mleft.getNode() << " " << absMinRight.getNode() << endl; + if( mleft.absLessThan(absMinRight) ){ + return true; + }else{ + return (!absMinRight.absLessThan(mleft)) && mleft < absMinRight; + } + } + } + }else{ + if(mleft.coefficientIsOne()){ + Debug("nf::tmp") + << "dfklj " << mleft.getNode() << endl + << pright.getNode() << endl + << pright.variableMonomialAreStrictlyGreater(mleft) + << endl; + return pright.variableMonomialAreStrictlyGreater(mleft); + }else{ + return false; + } + } + } }else{ - return *this; + return false; } } -bool Comparison::isIntegral() const { - return getRight().isIntegral() && getLeft().isIntegral(); +/** This must be (= qvarlist qpolynomial) or (= zmonomial zpolynomial)*/ +bool Comparison::isNormalEquality() const { + Assert(getNode().getKind() == kind::EQUAL); + + return isNormalEqualityOrDisequality(); } -bool Comparison::isConstant() const { - return getLeft().isConstant(); +/** + * This must be (not (= qvarlist qpolynomial)) or + * (not (= zmonomial zpolynomial)). + */ +bool Comparison::isNormalDistinct() const { + Assert(getNode().getKind() == kind::NOT); + Assert(getNode()[0].getKind() == kind::EQUAL); + + return isNormalEqualityOrDisequality(); } -Comparison Comparison::evaluateConstant() const { - Assert(left.isConstant()); - const Rational& rConst = getRight().getValue(); - const Rational& lConst = getLeft().getHead().getConstant().getValue(); - bool res = evaluateConstantPredicate(getKind(), lConst, rConst); - return Comparison(res); +Node Comparison::mkRatEquality(const Polynomial& p){ + Assert(!p.isConstant()); + Assert(!p.allIntegralVariables()); + + Monomial minimalVList = p.minimumVariableMonomial(); + Constant coeffInv = -(minimalVList.getConstant().inverse()); + + Polynomial newRight = (p - minimalVList) * coeffInv; + Polynomial newLeft(minimalVList.getVarList()); + + return toNode(kind::EQUAL, newLeft, newRight); } -Comparison Comparison::divideByLefthandGCD() const { - Assert(isIntegral()); +Node Comparison::mkRatInequality(Kind k, const Polynomial& p){ + Assert(k == kind::GEQ || k == kind::GT); + Assert(!p.isConstant()); + Assert(!p.allIntegralVariables()); + + SumPair sp = SumPair::mkSumPair(p); + Polynomial left = sp.getPolynomial(); + Constant right = - sp.getConstant(); + + Monomial minimalVList = left.getHead(); + Assert(!minimalVList.isConstant()); + + Constant coeffInv = minimalVList.getConstant().inverse().abs(); + Polynomial newLeft = left * coeffInv; + Constant newRight = right * (coeffInv); + + return toNode(k, newLeft, newRight); +} + +Node Comparison::mkIntInequality(Kind k, const Polynomial& p){ + Assert(kind::GT == k || kind::GEQ == k); + Assert(!p.isConstant()); + Assert(p.allIntegralVariables()); + + SumPair sp = SumPair::mkSumPair(p); + Polynomial left = sp.getPolynomial(); + Rational right = - (sp.getConstant().getValue()); + + Monomial m = left.getHead(); + Assert(!m.isConstant()); + + Integer lcm = left.denominatorLCM(); + Integer g = left.numeratorGCD(); + Rational mult(lcm,g); - Integer zr = getRight().getValue().getNumerator(); - Integer gcd = getLeft().gcd(); - Polynomial newLeft = getLeft().exactDivide(gcd); + Polynomial newLeft = left * mult; + Rational rightMult = right * mult; - Constant newRight = Constant::mkConstant(Rational(zr,gcd)); - return mkComparison(getKind(), newLeft, newRight); + + if(rightMult.isIntegral()){ + if(k == kind::GT){ + // (> p z) + // (>= p (+ z 1)) + Constant rightMultPlusOne = Constant::mkConstant(rightMult + 1); + return toNode(kind::GEQ, newLeft, rightMultPlusOne); + }else{ + Constant newRight = Constant::mkConstant(rightMult); + return toNode(kind::GEQ, newLeft, newRight); + } + }else{ + //(>= l (/ n d)) + //(>= l (ceil (/ n d))) + //This also hold for GT as (ceil (/ n d)) > (/ n d) + Integer ceilr = rightMult.ceiling(); + Constant ceilRight = Constant::mkConstant(ceilr); + return toNode(kind::GEQ, newLeft, ceilRight); + } } -Comparison Comparison::divideByLeadingCoefficient() const { - //Handle the rational/mixed case - Monomial head = getLeft().getHead(); - Constant leadingCoefficient = head.getConstant(); - Assert(!leadingCoefficient.isZero()); +Node Comparison::mkIntEquality(const Polynomial& p){ + Assert(!p.isConstant()); + Assert(p.allIntegralVariables()); + + SumPair sp = SumPair::mkSumPair(p); + Polynomial varPart = sp.getPolynomial(); + Constant constPart = sp.getConstant(); + + Integer lcm = varPart.denominatorLCM(); + Integer g = varPart.numeratorGCD(); + Constant mult = Constant::mkConstant(Rational(lcm,g)); - Constant inverse = leadingCoefficient.inverse(); + Constant constMult = constPart * mult; - return multiplyConstant(inverse); + if(constMult.isIntegral()){ + Polynomial varPartMult = varPart * mult; + + Monomial m = varPartMult.selectAbsMinimum(); + bool mIsPositive = m.getConstant().isPositive(); + + Polynomial noM = (varPartMult + (- m)) + Polynomial(constMult); + + // m + noM = 0 + Polynomial newRight = mIsPositive ? -noM : noM; + Polynomial newLeft = mIsPositive ? m : -m; + + Assert(newRight.isIntegral()); + return toNode(kind::EQUAL, newLeft, newRight); + }else{ + return mkBoolNode(false); + } } -Comparison Comparison::tightenIntegralConstraint() const { - Assert(getLeft().isIntegral()); +Comparison Comparison::mkComparison(Kind k, const Polynomial& l, const Polynomial& r){ - if(getRight().isIntegral()){ - return *this; + //Make this special case fast for sharing! + if((k == kind::EQUAL || k == kind::DISTINCT) && l.isVarList() && r.isVarList()){ + VarList vLeft = l.asVarList(); + VarList vRight = r.asVarList(); + + if(vLeft == vRight){ + return Comparison(k == kind::EQUAL); + }else{ + Node eqNode = vLeft < vRight ? toNode( kind::EQUAL, l, r) : toNode( kind::EQUAL, r, l); + Node forK = (k == kind::DISTINCT) ? eqNode.notNode() : eqNode; + return Comparison(forK); + } + } + + //General case + Polynomial diff = l - r; + if(diff.isConstant()){ + bool res = evaluateConstantPredicate(k, diff.asConstant(), Rational(0)); + return Comparison(res); }else{ - switch(getKind()){ + Node result = Node::null(); + bool isInteger = diff.allIntegralVariables(); + switch(k){ case kind::EQUAL: - //If the gcd of the left hand side does not cleanly divide the right hand side, - //this is unsatisfiable in the theory of Integers. - return Comparison(false); - case kind::GEQ: - case kind::GT: + result = isInteger ? mkIntEquality(diff) : mkRatEquality(diff); + break; + case kind::DISTINCT: { - //(>= l (/ n d)) - //(>= l (ceil (/ n d))) - //This also hold for GT as (ceil (/ n d)) > (/ n d) - Integer ceilr = getRight().getValue().ceiling(); - Constant newRight = Constant::mkConstant(ceilr); - return Comparison(toNode(kind::GEQ, getLeft(), newRight),kind::GEQ, getLeft(),newRight); + Node eq = isInteger ? mkIntEquality(diff) : mkRatEquality(diff); + result = eq.notNode(); } + break; case kind::LEQ: case kind::LT: { - //(<= l (/ n d)) - //(<= l (floor (/ n d))) - //This also hold for LT as (floor (/ n d)) < (/ n d) - Integer floor = getRight().getValue().floor(); - Constant newRight = Constant::mkConstant(floor); - return Comparison(toNode(kind::LEQ, getLeft(), newRight),kind::LEQ, getLeft(),newRight); + Polynomial neg = - diff; + Kind negKind = (k == kind::LEQ ? kind::GEQ : kind::GT); + result = isInteger ? + mkIntInequality(negKind, neg) : mkRatInequality(negKind, neg); } + break; + case kind::GEQ: + case kind::GT: + result = isInteger ? + mkIntInequality(k, diff) : mkRatInequality(k, diff); + break; default: - Unreachable(); + Unhandled(k); + } + Assert(!result.isNull()); + if(result.getKind() == kind::NOT && result[0].getKind() == kind::CONST_BOOLEAN){ + return Comparison(!(result[0].getConst<bool>())); + }else{ + Comparison cmp(result); + Assert(cmp.isNormalForm()); + return cmp; } } } -bool Comparison::isIntegerNormalForm() const{ - if(constantInLefthand()){ return false; } - else if(getLeft().getHead().getConstant().isNegative()){ return false; } - else if(!isIntegral()){ return false; } - else { - return getLeft().gcd() == 1; - } -} -bool Comparison::isMixedNormalForm() const { - if(constantInLefthand()){ return false; } - else if(allIntegralVariables()) { return false; } - else{ - return getLeft().getHead().getConstant().getValue() == 1; - } -} +// Comparison Comparison::normalize(Comparison c) { +// if(c.isConstant()){ +// return c.evaluateConstant(); +// }else{ +// Comparison c0 = c.constantInLefthand() ? c.cancelLefthandConstant() : c; +// Comparison c1 = c0.normalizeLeadingCoefficientPositive(); +// if(c1.allIntegralVariables()){ +// //All Integer Variable Case +// Comparison integer0 = c1.multiplyByDenominatorLCM(); +// Comparison integer1 = integer0.divideByLefthandGCD(); +// Comparison integer2 = integer1.tightenIntegralConstraint(); +// Assert(integer2.isBoolean() || integer2.isIntegerNormalForm()); +// return integer2; +// }else{ +// //Mixed case +// Comparison mixed = c1.divideByLeadingCoefficient(); +// Assert(mixed.isMixedNormalForm()); +// return mixed; +// } +// } +// } -Comparison Comparison::normalize(Comparison c) { - if(c.isConstant()){ - return c.evaluateConstant(); - }else{ - Comparison c0 = c.constantInLefthand() ? c.cancelLefthandConstant() : c; - Comparison c1 = c0.normalizeLeadingCoefficientPositive(); - if(c1.allIntegralVariables()){ - //All Integer Variable Case - Comparison integer0 = c1.multiplyByDenominatorLCM(); - Comparison integer1 = integer0.divideByLefthandGCD(); - Comparison integer2 = integer1.tightenIntegralConstraint(); - Assert(integer2.isBoolean() || integer2.isIntegerNormalForm()); - return integer2; - }else{ - //Mixed case - Comparison mixed = c1.divideByLeadingCoefficient(); - Assert(mixed.isMixedNormalForm()); - return mixed; - } - } +bool Comparison::isBoolean() const { + return getNode().getKind() == kind::CONST_BOOLEAN; } -Comparison Comparison::mkNormalComparison(Kind k, const Polynomial& left, const Constant& right) { - Comparison cmp = mkComparison(k,left,right); - Comparison normalized = cmp.normalize(cmp); - Assert(normalized.isNormalForm()); - return normalized; + +bool Comparison::debugIsIntegral() const{ + return getLeft().isIntegral() && getRight().isIntegral(); } -Node Polynomial::computeQR(const Polynomial& p, const Integer& div){ - Assert(p.isIntegral()); - std::vector<Monomial> q_vec, r_vec; - Integer tmp_q, tmp_r; - for(iterator iter = p.begin(), pend = p.end(); iter != pend; ++iter){ - Monomial curr = *iter; - VarList vl = curr.getVarList(); - Constant c = curr.getConstant(); +// Comparison Comparison::mkComparison(Kind k, const Polynomial& left, const Constant& right) { +// Assert(isRelationOperator(k)); +// if(left.isConstant()) { +// const Rational& lConst = left.getNode().getConst<Rational>(); +// const Rational& rConst = right.getNode().getConst<Rational>(); +// bool res = evaluateConstantPredicate(k, lConst, rConst); +// return Comparison(res); +// } - const Integer& a = c.getValue().getNumerator(); - Integer::floorQR(tmp_q, tmp_r, a, div); - Constant q=Constant::mkConstant(tmp_q); - Constant r=Constant::mkConstant(tmp_r); - if(!q.isZero()){ - q_vec.push_back(Monomial::mkMonomial(q, vl)); - } - if(!r.isZero()){ - r_vec.push_back(Monomial::mkMonomial(r, vl)); - } - } +// if(left.getNode().getType().isPseudoboolean()) { +// bool result; +// if(pbComparison(k, left.getNode(), right.getNode().getConst<Rational>(), result)) { +// return Comparison(result); +// } +// } - Polynomial p_q = Polynomial::mkPolynomial(q_vec); - Polynomial p_r = Polynomial::mkPolynomial(r_vec); +// return Comparison(toNode(k, left, right), k, left, right); +// } - return NodeManager::currentNM()->mkNode(kind::PLUS, p_q.getNode(), p_r.getNode()); -} +// Comparison Comparison::mkComparison(Kind k, const Polynomial& left, const Polynomial& right) { +// Assert(isRelationOperator(k)); +// return Comparison(toNode(k, left, right), k, left, right); +// } -Node SumPair::computeQR(const SumPair& sp, const Integer& div){ - Assert(sp.isIntegral()); - const Integer& constant = sp.getConstant().getValue().getNumerator(); +// bool Comparison::constantInLefthand() const{ +// return getLeft().containsConstant(); +// } - Integer constant_q, constant_r; - Integer::floorQR(constant_q, constant_r, constant, div); +// Comparison Comparison::cancelLefthandConstant() const { +// if(constantInLefthand()){ +// Monomial constantHead = getLeft().getHead(); +// Assert(constantHead.isConstant()); - Node p_qr = Polynomial::computeQR(sp.getPolynomial(), div); - Assert(p_qr.getKind() == kind::PLUS); - Assert(p_qr.getNumChildren() == 2); +// Constant constant = constantHead.getConstant(); +// Constant negativeConstantHead = -constant; +// return addConstant(negativeConstantHead); +// }else{ +// return *this; +// } +// } - Polynomial p_q = Polynomial::parsePolynomial(p_qr[0]); - Polynomial p_r = Polynomial::parsePolynomial(p_qr[1]); +// Integer OrderedPolynomialPair::denominatorLCM() const { +// // Get the coefficients to be all integers. +// Integer firstDenominatorLCM = getFirst().denominatorLCM(); +// Integer secondDenominatorLCM = getSecond().denominatorLCM(); +// Integer denominatorLCM = secondDenominatorLCM.lcm(secondDenominatorLCM); +// Assert(denominatorLCM.sgn() > 0); +// return denominatorLCM; +// } - SumPair sp_q(p_q, Constant::mkConstant(constant_q)); - SumPair sp_r(p_r, Constant::mkConstant(constant_r)); +// bool Comparison::isIntegral() const { +// return getRight().isIntegral() && getLeft().isIntegral(); +// } - return NodeManager::currentNM()->mkNode(kind::PLUS, sp_q.getNode(), sp_r.getNode()); -} +// bool OrderedPolynomialPair::isConstant() const { +// return getFirst().isConstant() && getSecond().isConstant(); +// } -Constant Polynomial::getCoefficient(const VarList& vl) const{ - //TODO improve to binary search... - for(iterator iter=begin(), myend=end(); iter != myend; ++iter){ - Monomial m = *iter; - VarList curr = m.getVarList(); - if(curr == vl){ - return m.getConstant(); +// bool OrderedPolynomialPair::evaluateConstant(Kind k) const { +// Assert(getFirst().isConstant()); +// Assert(getSecond().isConstant()); + +// const Rational& firstConst = getFirst().asConstant(); +// const Rational& secondConst = getSecond().asConstant(); + +// return evaluateConstantPredicate(k, firstConst, secondConst); +// } + +// OrderedPolynomialPair OrderedPolynomialPair::divideByGCD() const { +// Assert(isIntegral()); + +// Integer fGcd = getFirst().gcd(); +// Integer sGcd = getSecond().gcd(); + +// Integer gcd = fGcd.gcd(sGcd); +// Polynomial newFirst = getFirst().exactDivide(gcd); +// Polynomial newSecond = getSecond().exactDivide(gcd); + +// return OrderedPolynomialPair(newFirst, newSecond); +// } + +// OrderedPolynomialPair OrderedPolynomialPair::divideByLeadingFirstCoefficient() const { +// //Handle the rational/mixed case +// Monomial head = getFirst().getHead(); +// Constant leadingCoefficient = head.getConstant(); +// Assert(!leadingCoefficient.isZero()); + +// Constant inverse = leadingCoefficient.inverse(); + +// return multiplyConstant(inverse); +// } + +// OrderedPolynomialPair OrderedPolynomialPair::multiplyConstant(const Constant& c) const { +// return OrderedPolynomialPair(getFirst() * c, getSecond() * c); +// } + +// Comparison Comparison::divideByLeadingCoefficient() const { +// //Handle the rational/mixed case +// Monomial head = getLeft().getHead(); +// Constant leadingCoefficient = head.getConstant(); +// Assert(!leadingCoefficient.isZero()); + +// Constant inverse = leadingCoefficient.inverse(); + +// return multiplyConstant(inverse); +// } + + + +// Comparison Comparison::tightenIntegralConstraint() const { +// Assert(getLeft().isIntegral()); + +// if(getRight().isIntegral()){ +// return *this; +// }else{ +// switch(getKind()){ +// case kind::EQUAL: +// //If the gcd of the left hand side does not cleanly divide the right hand side, +// //this is unsatisfiable in the theory of Integers. +// return Comparison(false); +// case kind::GEQ: +// case kind::GT: +// { +// //(>= l (/ n d)) +// //(>= l (ceil (/ n d))) +// //This also hold for GT as (ceil (/ n d)) > (/ n d) +// Integer ceilr = getRight().getValue().ceiling(); +// Constant newRight = Constant::mkConstant(ceilr); +// return Comparison(toNode(kind::GEQ, getLeft(), newRight),kind::GEQ, getLeft(),newRight); +// } +// case kind::LEQ: +// case kind::LT: +// { +// //(<= l (/ n d)) +// //(<= l (floor (/ n d))) +// //This also hold for LT as (floor (/ n d)) < (/ n d) +// Integer floor = getRight().getValue().floor(); +// Constant newRight = Constant::mkConstant(floor); +// return Comparison(toNode(kind::LEQ, getLeft(), newRight),kind::LEQ, getLeft(),newRight); +// } +// default: +// Unreachable(); +// } +// } +// } + +// bool Comparison::isIntegerNormalForm() const{ +// if(constantInLefthand()){ return false; } +// else if(getLeft().getHead().getConstant().isNegative()){ return false; } +// else if(!isIntegral()){ return false; } +// else { +// return getLeft().gcd() == 1; +// } +// } +// bool Comparison::isMixedNormalForm() const { +// if(constantInLefthand()){ return false; } +// else if(allIntegralVariables()) { return false; } +// else{ +// return getLeft().getHead().getConstant().getValue() == 1; +// } +// } + +// Comparison Comparison::normalize(Comparison c) { +// if(c.isConstant()){ +// return c.evaluateConstant(); +// }else{ +// Comparison c0 = c.constantInLefthand() ? c.cancelLefthandConstant() : c; +// Comparison c1 = c0.normalizeLeadingCoefficientPositive(); +// if(c1.allIntegralVariables()){ +// //All Integer Variable Case +// Comparison integer0 = c1.multiplyByDenominatorLCM(); +// Comparison integer1 = integer0.divideByLefthandGCD(); +// Comparison integer2 = integer1.tightenIntegralConstraint(); +// Assert(integer2.isBoolean() || integer2.isIntegerNormalForm()); +// return integer2; +// }else{ +// //Mixed case +// Comparison mixed = c1.divideByLeadingCoefficient(); +// Assert(mixed.isMixedNormalForm()); +// return mixed; +// } +// } +// } + +// Comparison Comparison::mkNormalComparison(Kind k, const Polynomial& left, const Constant& right) { +// Comparison cmp = mkComparison(k,left,right); +// Comparison normalized = cmp.normalize(cmp); +// Assert(normalized.isNormalForm()); +// return normalized; +// } + + +Kind Comparison::comparisonKind(TNode literal){ + switch(literal.getKind()){ + case kind::CONST_BOOLEAN: + case kind::GT: + case kind::GEQ: + case kind::EQUAL: + return literal.getKind(); + case kind::NOT: + { + TNode negatedAtom = literal[0]; + switch(negatedAtom.getKind()){ + case kind::GT: //(not (GT x c)) <=> (LEQ x c) + return kind::LEQ; + case kind::GEQ: //(not (GEQ x c)) <=> (LT x c) + return kind::LT; + case kind::EQUAL: + return kind::DISTINCT; + default: + return kind::UNDEFINED_KIND; + } } + default: + return kind::UNDEFINED_KIND; } - return Constant::mkConstant(0); } } //namespace arith diff --git a/src/theory/arith/normal_form.h b/src/theory/arith/normal_form.h index a5e1e0cec..434be42a2 100644 --- a/src/theory/arith/normal_form.h +++ b/src/theory/arith/normal_form.h @@ -49,7 +49,7 @@ namespace arith { * * variable := n * where - * n.getMetaKind() == metakind::VARIABLE + * n.getMetaKind() == metakind::VARIABLE or is foreign * n.getType() \in {Integer, Real} * * constant := n @@ -71,24 +71,45 @@ namespace arith { * isStrictlySorted monoOrder [monomial] * forall (\x -> x != 0) [monomial] * - * rational_restricted_cmp := (|><| qpolynomial constant) + * rational_cmp := (|><| qpolynomial constant) * where - * |><| is GEQ, EQ, or EQ + * |><| is GEQ, or GT * not (exists constantMonomial (monomialList qpolynomial)) * (exists realMonomial (monomialList qpolynomial)) - * monomialCoefficient (head (monomialList qpolynomial)) == 1 + * abs(monomialCoefficient (head (monomialList qpolynomial))) == 1 * - * integer_restricted_cmp := (|><| zpolynomial constant) + * integer_cmp := (<= zpolynomial constant) * where - * |><| is GEQ, EQ, or EQ * not (exists constantMonomial (monomialList zpolynomial)) - * (forall integerMonomial (monomialList qpolynomial)) + * (forall integerMonomial (monomialList zpolynomial)) + * the gcd of all numerators of coefficients is 1 * the denominator of all coefficients and the constant is 1 + * + * rational_eq := (= qvarlist qpolynomial) + * where + * let allMonomials = (cons qvarlist (monomialList zpolynomial)) + * let variableMonomials = (drop constantMonomial allMonomials) + * isStrictlySorted variableMonomials + * exists realMonomial variableMonomials + * is not empty qvarlist + * + * integer_eq := (= zmonomial zpolynomial) + * where + * let allMonomials = (cons zmonomial (monomialList zpolynomial)) + * let variableMonomials = (drop constantMonomial allMonomials) + * not (constantMonomial zmonomial) + * (forall integerMonomial allMonomials) + * isStrictlySorted variableMonomials * the gcd of all numerators of coefficients is 1 + * the denominator of all coefficients and the constant is 1 + * the coefficient of monomial is positive + * the value of the coefficient of monomial is minimal in variableMonomials * * comparison := TRUE | FALSE - * | rational_restricted_cmp | (not rational_restricted_cmp) - * | integer_restricted_cmp | (not integer_restricted_cmp) + * | rational_cmp | (not rational_cmp) + * | rational_eq | (not rational_eq) + * | integer_cmp | (not integer_cmp) + * | integer_eq | (not integer_eq) * * Normal Form for terms := polynomial * Normal Form for atoms := comparison @@ -138,6 +159,15 @@ namespace arith { * Section 3: Guard Conditions Misc. * * + * variable_order x y = + * if (meta_kind_variable x) and (meta_kind_variable y) + * then node_order x y + * else if (meta_kind_variable x) + * then false + * else if (meta_kind_variable y) + * then true + * else node_order x y + * * var_list_len vl = * match vl with * variable -> 1 @@ -214,7 +244,27 @@ public: return getNode().getType().isInteger(); } - bool operator<(const Variable& v) const { return getNode() < v.getNode();} + bool isMetaKindVariable() const { + return getNode().getMetaKind() == kind::metakind::VARIABLE; + } + + bool operator<(const Variable& v) const { + bool thisIsVariable = isMetaKindVariable(); + bool vIsVariable = v.isMetaKindVariable(); + + if(thisIsVariable == vIsVariable){ + bool thisIsInteger = isIntegral(); + bool vIsInteger = v.isIntegral(); + if(thisIsInteger == vIsInteger){ + return getNode() < v.getNode(); + }else{ + return thisIsInteger && !vIsInteger; + } + }else{ + return thisIsVariable && !vIsVariable; + } + } + bool operator==(const Variable& v) const { return getNode() == v.getNode();} };/* class Variable */ @@ -240,6 +290,14 @@ public: return Constant(mkRationalNode(rat)); } + static Constant mkZero() { + return mkConstant(Rational(0)); + } + + static Constant mkOne() { + return mkConstant(Rational(1)); + } + const Rational& getValue() const { return getNode().getConst<Rational>(); } @@ -254,6 +312,10 @@ public: bool isOne() const { return getValue() == 1; } + Constant operator*(const Rational& other) const { + return mkConstant(getValue() * other); + } + Constant operator*(const Constant& other) const { return mkConstant(getValue() * other.getValue()); } @@ -572,9 +634,18 @@ public: return coefficientIsOne() || constant.getValue() == -1; } + bool constantIsPositive() const { + return getConstant().isPositive(); + } + + Monomial operator*(const Rational& q) const; Monomial operator*(const Constant& c) const; Monomial operator*(const Monomial& mono) const; + Monomial operator-() const{ + return (*this) * Rational(-1); + } + int cmp(const Monomial& mono) const { return getVarList().cmp(mono.getVarList()); @@ -636,6 +707,8 @@ public: };/* class Monomial */ +class SumPair; +class Comparison;; class Polynomial : public NodeWrapper { private: @@ -795,6 +868,9 @@ public: return mkPolynomial(subrange); } + Monomial minimumVariableMonomial() const; + bool variableMonomialAreStrictlyGreater(const Monomial& m) const; + void printList() const { if(Debug.isOn("normal-form")){ Debug("normal-form") << "start list" << std::endl; @@ -834,6 +910,12 @@ public: */ Monomial selectAbsMinimum() const; + /** Returns true if the absolute value of the head coefficient is one. */ + bool leadingCoefficientIsAbsOne() const; + bool leadingCoefficientIsPositive() const; + bool denominatorLCMIsOne() const; + bool numeratorGCDIsOne() const; + /** * Returns the Least Common Multiple of the denominators of the coefficients * of the monomials. @@ -841,6 +923,12 @@ public: Integer denominatorLCM() const; /** + * Returns the GCD of the numerators of the monomials. + * Requires this to be an isIntegral() polynomial. + */ + Integer numeratorGCD() const; + + /** * Returns the GCD of the coefficients of the monomials. * Requires this to be an isIntegral() polynomial. */ @@ -856,7 +944,11 @@ public: Polynomial operator+(const Polynomial& vl) const; Polynomial operator-(const Polynomial& vl) const; + Polynomial operator-() const{ + return (*this) * Rational(-1); + } + Polynomial operator*(const Rational& q) const; Polynomial operator*(const Constant& c) const; Polynomial operator*(const Monomial& mono) const; @@ -905,168 +997,31 @@ public: return 1; } } -};/* class Polynomial */ - - -class Comparison : public NodeWrapper { -private: - Kind oper; - Polynomial left; - Constant right; - - static Node toNode(Kind k, const Polynomial& l, const Constant& r); - - Comparison(TNode n, Kind k, const Polynomial& l, const Constant& r): - NodeWrapper(n), oper(k), left(l), right(r) - { } - - /** - * Possibly simplify a comparison with a pseudoboolean-typed LHS. k - * is one of LT, LEQ, EQUAL, GEQ, GT, and left must be PB-typed. If - * possible, "left k right" is fully evaluated, "true" is returned, - * and the result of the evaluation is returned in "result". If no - * evaluation is possible, false is returned and "result" is - * untouched. - * - * For example, pbComparison(kind::EQUAL, "x", 0.5, result) returns - * true, and updates "result" to false, since pseudoboolean variable - * "x" can never equal 0.5. pbComparison(kind::GEQ, "x", 1, result) - * returns false, since "x" can be >= 1, but could also be less. - */ - static bool pbComparison(Kind k, TNode left, const Rational& right, bool& result); - Kind getKind() const { return oper; } - -public: - Comparison(bool val) : - NodeWrapper(NodeManager::currentNM()->mkConst(val)), - oper(kind::CONST_BOOLEAN), - left(Polynomial::mkZero()), - right(Constant::mkConstant(0)) - { } - - Comparison(Kind k, const Polynomial& l, const Constant& r): - NodeWrapper(toNode(k, l, r)), oper(k), left(l), right(r) - { - Assert(isRelationOperator(oper)); - Assert(!left.containsConstant()); - Assert(left.getHead().getConstant().isOne()); - } - - static Comparison mkComparison(Kind k, const Polynomial& left, const Constant& right); - - /** - * Returns the left hand side of the comparison. - * This is a polynomial that always contains all of the variables. - */ - const Polynomial& getLeft() const { return left; } - - /** - * Returns the right hand constatn of the comparison. - * If in normal form, this is the only constant term. - */ - const Constant& getRight() const { return right; } - - /** Returns true if the comparison is a boolean constant. */ - bool isBoolean() const { - return (oper == kind::CONST_BOOLEAN); - } - - /** Returns true if all of the variables are integers. */ - bool allIntegralVariables() const { - return getLeft().allIntegralVariables(); + const Rational& asConstant() const{ + Assert(isConstant()); + return getNode().getConst<Rational>(); + //return getHead().getConstant().getValue(); } - /** - * Returns true if the comparison is either a boolean term, - * in integer normal form or mixed normal form. - */ - bool isNormalForm() const { - if(isBoolean()) { - return true; - } else if(allIntegralVariables()) { - return isIntegerNormalForm(); - } else{ - return isMixedNormalForm(); + bool isVarList() const { + if(singleton()){ + return VarList::isMember(getNode()); + }else{ + return false; } } -private: - /** Normal form check if at least one variable is real. */ - bool isMixedNormalForm() const; - - /** Normal form check is all variables are real.*/ - bool isIntegerNormalForm() const; - -public: - /** - * Returns true if the left hand side is the sum of a non-zero constant - * and a polynomial.*/ - bool constantInLefthand() const; - - /** - * Returns a polynomial that is equivalent to the original but does not contain - * a constant in the top level sum on the left hand side. - */ - Comparison cancelLefthandConstant() const; - - - /** Returns true if the polynomial is a constant. */ - bool isConstant() const; - - /** Reduces a constant comparison to a boolean comaprison.*/ - Comparison evaluateConstant() const; - - - /** - * Returns true if all of the variables are integers, the coefficients are integers, - * and the right hand coefficient is an integer. - */ - bool isIntegral() const; - - /** - * Returns the Least Common Multiple of the monomials - * on the lefthand side and the constant on the right. - */ - Integer denominatorLCM() const; - - /** Multiplies the comparison by the denominatorLCM(). */ - Comparison multiplyByDenominatorLCM() const; - - /** If the leading coefficient is negative, multiply by -1. */ - Comparison normalizeLeadingCoefficientPositive() const; - - /** Divides the Comaprison by the gcd of the lefthand.*/ - Comparison divideByLefthandGCD() const; - - /** Divides the Comparison by the leading coefficient. */ - Comparison divideByLeadingCoefficient() const; - - /** - * If the left hand is integral and the right hand is not, - * the comparison is tightened to the nearest integer. - */ - Comparison tightenIntegralConstraint() const; - - Comparison addConstant(const Constant& constant) const; - - /* Multiply a non-boolean comparison by a constant term. */ - Comparison multiplyConstant(const Constant& constant) const; - - static Comparison parseNormalForm(TNode n); - - /* Returns a logically equivalent comparison in normal form. */ - static Comparison normalize(Comparison c); + VarList asVarList() const { + Assert(isVarList()); + return getHead().getVarList(); + } - /** Makes a comparison that is in normal form. */ - static Comparison mkNormalComparison(Kind k, const Polynomial& left, const Constant& right); + friend class SumPair; + friend class Comparison;; - inline static bool isNormalAtom(TNode n){ - Comparison parse = Comparison::parseNormalForm(n); - return parse.isNormalForm(); - } +};/* class Polynomial */ -};/* class Comparison */ /** * SumPair is a utility class that extends polynomials for use in computations. @@ -1147,6 +1102,8 @@ public: return (*this) + (other * Constant::mkConstant(-1)); } + static SumPair mkSumPair(const Polynomial& p); + static SumPair mkSumPair(const Variable& var){ return SumPair(Polynomial::mkPolynomial(var)); } @@ -1187,12 +1144,183 @@ public: static Node computeQR(const SumPair& sp, const Integer& div); +};/* class SumPair */ + +/* class OrderedPolynomialPair { */ +/* private: */ +/* Polynomial d_first; */ +/* Polynomial d_second; */ +/* public: */ +/* OrderedPolynomialPair(const Polynomial& f, const Polynomial& s) */ +/* : d_first(f), */ +/* d_second(s) */ +/* {} */ + +/* /\** Returns the first part of the pair. *\/ */ +/* const Polynomial& getFirst() const { */ +/* return d_first; */ +/* } */ + +/* /\** Returns the second part of the pair. *\/ */ +/* const Polynomial& getSecond() const { */ +/* return d_second; */ +/* } */ + +/* OrderedPolynomialPair operator*(const Constant& c) const; */ +/* OrderedPolynomialPair operator+(const Polynomial& p) const; */ + +/* /\** Returns true if both of the polynomials are constant. *\/ */ +/* bool isConstant() const; */ + +/* /\** */ +/* * Evaluates an isConstant() ordered pair as if */ +/* * (k getFirst() getRight()) */ +/* *\/ */ +/* bool evaluateConstant(Kind k) const; */ + +/* /\** */ +/* * Returns the Least Common Multiple of the monomials */ +/* * on the lefthand side and the constant on the right. */ +/* *\/ */ +/* Integer denominatorLCM() const; */ + +/* /\** Constructs a SumPair. *\/ */ +/* SumPair toSumPair() const; */ + + +/* OrderedPolynomialPair divideByGCD() const; */ +/* OrderedPolynomialPair multiplyConstant(const Constant& c) const; */ + +/* /\** */ +/* * Returns true if all of the variables are integers, */ +/* * and the coefficients are integers. */ +/* *\/ */ +/* bool isIntegral() const; */ + +/* /\** Returns true if all of the variables are integers. *\/ */ +/* bool allIntegralVariables() const { */ +/* return getFirst().allIntegralVariables() && getSecond().allIntegralVariables(); */ +/* } */ +/* }; */ + +class Comparison : public NodeWrapper { +private: + + static Node toNode(Kind k, const Polynomial& l, const Constant& c); + static Node toNode(Kind k, const Polynomial& l, const Polynomial& r); + + Comparison(TNode n); + + /** + * Creates a node in normal form equivalent to (= l 0). + * All variables in l are integral. + */ + static Node mkIntEquality(const Polynomial& l); + + /** + * Creates a comparison equivalent to (k l 0). + * k is either GT or GEQ. + * All variables in l are integral. + */ + static Node mkIntInequality(Kind k, const Polynomial& l); - static SumPair comparisonToSumPair(const Comparison& cmp){ - return SumPair(cmp.getLeft(), - cmp.getRight()); + /** + * Creates a node equivalent to (= l 0). + * It is not the case that all variables in l are integral. + */ + static Node mkRatEquality(const Polynomial& l); + + /** + * Creates a comparison equivalent to (k l 0). + * k is either GT or GEQ. + * It is not the case that all variables in l are integral. + */ + static Node mkRatInequality(Kind k, const Polynomial& l); + +public: + + Comparison(bool val) : + NodeWrapper(NodeManager::currentNM()->mkConst(val)) + { } + + /** + * Given a literal to TheoryArith return a single kind to + * to indicate its underlying structure. + * The function returns the following in each case: + * - (K left right) -> K where is either EQUAL, GT, or GEQ + * - (CONST_BOOLEAN b) -> CONST_BOOLEAN + * - (NOT (EQUAL left right)) -> DISTINCT + * - (NOT (GT left right)) -> LEQ + * - (NOT (GEQ left right)) -> LT + * If none of these match, it returns UNDEFINED_KIND. + */ + static Kind comparisonKind(TNode literal); + + Kind comparisonKind() const { return comparisonKind(getNode()); } + + static Comparison mkComparison(Kind k, const Polynomial& l, const Polynomial& r); + + /** Returns true if the comparison is a boolean constant. */ + bool isBoolean() const; + + /** + * Returns true if the comparison is either a boolean term, + * in integer normal form or mixed normal form. + */ + bool isNormalForm() const; + +private: + bool isNormalGT() const; + bool isNormalGEQ() const; + + bool isNormalLT() const; + bool isNormalLEQ() const; + + bool isNormalEquality() const; + bool isNormalDistinct() const; + bool isNormalEqualityOrDisequality() const; + + bool allIntegralVariables() const { + return getLeft().allIntegralVariables() && getRight().allIntegralVariables(); } + bool rightIsConstant() const; -};/* class SumPair */ +public: + Polynomial getLeft() const; + Polynomial getRight() const; + + /* /\** Normal form check if at least one variable is real. *\/ */ + /* bool isMixedCompareNormalForm() const; */ + + /* /\** Normal form check if at least one variable is real. *\/ */ + /* bool isMixedEqualsNormalForm() const; */ + + /* /\** Normal form check is all variables are integer.*\/ */ + /* bool isIntegerCompareNormalForm() const; */ + + /* /\** Normal form check is all variables are integer.*\/ */ + /* bool isIntegerEqualsNormalForm() const; */ + + + /** + * Returns true if all of the variables are integers, the coefficients are integers, + * and the right hand coefficient is an integer. + */ + bool debugIsIntegral() const; + + static Comparison parseNormalForm(TNode n); + + inline static bool isNormalAtom(TNode n){ + Comparison parse = Comparison::parseNormalForm(n); + return parse.isNormalForm(); + } + + SumPair toSumPair() const; + + Polynomial normalizedVariablePart() const; + DeltaRational normalizedDeltaRational() const; + +};/* class Comparison */ }/* CVC4::theory::arith namespace */ }/* CVC4::theory namespace */ diff --git a/src/theory/arith/ordered_set.h b/src/theory/arith/ordered_set.h deleted file mode 100644 index 8887daa8d..000000000 --- a/src/theory/arith/ordered_set.h +++ /dev/null @@ -1,116 +0,0 @@ -/********************* */ -/*! \file ordered_set.h - ** \verbatim - ** Original author: taking - ** Major contributors: none - ** Minor contributors (to current version): none - ** This file is part of the CVC4 prototype. - ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys) - ** Courant Institute of Mathematical Sciences - ** New York University - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim - ** - ** \brief [[ Add one-line brief description here ]] - ** - ** [[ Add lengthier description here ]] - ** \todo document this file - **/ - -#include "cvc4_private.h" - -#ifndef __CVC4__THEORY__ARITH__ORDERED_SET_H -#define __CVC4__THEORY__ARITH__ORDERED_SET_H - -#include <map> -#include <set> -#include "expr/kind.h" -#include "expr/node.h" -#include "util/Assert.h" -#include "theory/arith/arith_utilities.h" - - -namespace CVC4 { -namespace theory { -namespace arith { - -inline const Rational& rightHandRational(TNode ineq){ - Assert(ineq.getKind() == kind::LEQ - || ineq.getKind() == kind::GEQ - || ineq.getKind() == kind::EQUAL); - TNode righthand = ineq[1]; - Assert(righthand.getKind() == kind::CONST_RATIONAL); - return righthand.getConst<Rational>(); -} - -class BoundValueEntry { -private: - const Rational& value; - TNode d_leq, d_geq; - - BoundValueEntry(const Rational& v, TNode l, TNode g): - value(v), - d_leq(l), - d_geq(g) - {} - -public: - Node getLeq() const{ - Assert(hasLeq()); - return d_leq; - } - Node getGeq() const{ - Assert(hasGeq()); - return d_geq; - } - - static BoundValueEntry mkFromLeq(TNode leq){ - Assert(leq.getKind() == kind::LEQ); - return BoundValueEntry(rightHandRational(leq), leq, TNode::null()); - } - - static BoundValueEntry mkFromGeq(TNode geq){ - Assert(geq.getKind() == kind::GEQ); - return BoundValueEntry(rightHandRational(geq), TNode::null(), geq); - } - - void addLeq(TNode leq){ - Assert(leq.getKind() == kind::LEQ); - Assert(rightHandRational(leq) == getValue()); - // [MGD] With context-dependent pre-registration, we could get the - // same one twice - Assert(!hasLeq() || d_leq == leq); - d_leq = leq; - } - - void addGeq(TNode geq){ - Assert(geq.getKind() == kind::GEQ); - Assert(rightHandRational(geq) == getValue()); - // [MGD] With context-dependent pre-registration, we could get the - // same one twice - Assert(!hasGeq() || d_geq == geq); - d_geq = geq; - } - - bool hasGeq() const { return d_geq != TNode::null(); } - bool hasLeq() const { return d_leq != TNode::null(); } - - - const Rational& getValue() const{ - return value; - } - - bool operator<(const BoundValueEntry& other){ - return value < other.value; - } -}; - -typedef std::map<Rational, BoundValueEntry> BoundValueSet; - -typedef std::set<TNode, RightHandRationalLT> EqualValueSet; - -}/* CVC4::theory::arith namespace */ -}/* CVC4::theory namespace */ -}/* CVC4 namespace */ - -#endif /* __CVC4__THEORY__ARITH__ORDERED_SET_H */ diff --git a/src/theory/arith/partial_model.cpp b/src/theory/arith/partial_model.cpp index 65b0083d9..32c9f6adc 100644 --- a/src/theory/arith/partial_model.cpp +++ b/src/theory/arith/partial_model.cpp @@ -20,6 +20,7 @@ #include "theory/arith/partial_model.h" #include "util/output.h" +#include "theory/arith/constraint.h" using namespace std; @@ -27,62 +28,26 @@ namespace CVC4 { namespace theory { namespace arith { - - -bool ArithPartialModel::boundsAreEqual(ArithVar x){ +ArithPartialModel::ArithPartialModel(context::Context* c) + : d_mapSize(0), + d_hasSafeAssignment(), + d_assignment(), + d_safeAssignment(), + d_ubc(c), + d_lbc(c), + d_deltaIsSafe(false), + d_delta(-1,1), + d_history() +{ } + +bool ArithPartialModel::boundsAreEqual(ArithVar x) const{ if(hasLowerBound(x) && hasUpperBound(x)){ - return d_upperBound[x] == d_lowerBound[x]; + return getUpperBound(x) == getLowerBound(x); }else{ return false; } } -void ArithPartialModel::zeroDifferenceDetected(ArithVar x){ - Assert(d_dm.isDifferenceSlack(x)); - Assert(upperBoundIsZero(x)); - Assert(lowerBoundIsZero(x)); - - Node lb = getLowerConstraint(x); - Node ub = getUpperConstraint(x); - Node reason = lb != ub ? lb.andNode(ub) : lb; - d_dm.differenceIsZero(x, reason); -} - -void ArithPartialModel::setUpperBound(ArithVar x, const DeltaRational& r){ - d_deltaIsSafe = false; - - Debug("partial_model") << "setUpperBound(" << x << "," << r << ")" << endl; - d_hasHadABound[x] = true; - d_upperBound.set(x,r); - - if(d_dm.isDifferenceSlack(x)){ - int sgn = r.sgn(); - if(sgn < 0){ - d_dm.differenceCannotBeZero(x, getUpperConstraint(x)); - }else if(sgn == 0 && lowerBoundIsZero(x)){ - zeroDifferenceDetected(x); - } - } -} - -void ArithPartialModel::setLowerBound(ArithVar x, const DeltaRational& r){ - d_deltaIsSafe = false; - - Debug("partial_model") << "setLowerBound(" << x << "," << r << ")" << endl; - d_hasHadABound[x] = true; - d_lowerBound.set(x,r); - - - if(d_dm.isDifferenceSlack(x)){ - int sgn = r.sgn(); - if(sgn > 0){ - d_dm.differenceCannotBeZero(x, getLowerConstraint(x)); - }else if(sgn == 0 && upperBoundIsZero(x)){ - zeroDifferenceDetected(x); - } - } -} - void ArithPartialModel::setAssignment(ArithVar x, const DeltaRational& r){ Debug("partial_model") << "pm: updating the assignment to" << x << " now " << r <<endl; @@ -114,14 +79,12 @@ void ArithPartialModel::setAssignment(ArithVar x, const DeltaRational& safe, con } bool ArithPartialModel::equalSizes(){ - return d_mapSize == d_hasHadABound.size() && + return d_mapSize == d_hasSafeAssignment.size() && d_mapSize == d_assignment.size() && d_mapSize == d_safeAssignment.size() && - d_mapSize == d_upperBound.size() && - d_mapSize == d_lowerBound.size() && - d_mapSize == d_upperConstraint.size() && - d_mapSize == d_lowerConstraint.size(); + d_mapSize == d_ubc.size() && + d_mapSize == d_lbc.size(); } void ArithPartialModel::initialize(ArithVar x, const DeltaRational& r){ @@ -129,33 +92,27 @@ void ArithPartialModel::initialize(ArithVar x, const DeltaRational& r){ Assert(equalSizes()); ++d_mapSize; - - d_hasHadABound.push_back( false ); - d_hasSafeAssignment.push_back( false ); d_assignment.push_back( r ); d_safeAssignment.push_back( DeltaRational(0) ); - d_upperBound.push_back( DeltaRational(0) ); - d_lowerBound.push_back( DeltaRational(0) ); - - d_upperConstraint.push_back( TNode::null() ); - d_lowerConstraint.push_back( TNode::null() ); + d_ubc.push_back(NullConstraint); + d_lbc.push_back(NullConstraint); } /** Must know that the bound exists both calling this! */ -const DeltaRational& ArithPartialModel::getUpperBound(ArithVar x) { +const DeltaRational& ArithPartialModel::getUpperBound(ArithVar x) const { Assert(inMaps(x)); Assert(hasUpperBound(x)); - return d_upperBound[x]; + return getUpperBoundConstraint(x)->getValue(); } -const DeltaRational& ArithPartialModel::getLowerBound(ArithVar x) { +const DeltaRational& ArithPartialModel::getLowerBound(ArithVar x) const { Assert(inMaps(x)); Assert(hasLowerBound(x)); - return d_lowerBound[x]; + return getLowerBoundConstraint(x)->getValue(); } const DeltaRational& ArithPartialModel::getSafeAssignment(ArithVar x) const{ @@ -182,144 +139,93 @@ const DeltaRational& ArithPartialModel::getAssignment(ArithVar x) const{ } - -void ArithPartialModel::setLowerConstraint(ArithVar x, TNode constraint){ - Debug("partial_model") << "setLowerConstraint(" - << x << ":" << constraint << ")" << endl; +void ArithPartialModel::setLowerBoundConstraint(Constraint c){ + AssertArgument(c != NullConstraint, "Cannot set a lower bound to NullConstraint."); + AssertArgument(c->isEquality() || c->isLowerBound(), + "Constraint type must be set to an equality or UpperBound."); + ArithVar x = c->getVariable(); + Debug("partial_model") << "setLowerBoundConstraint(" << x << ":" << c << ")" << endl; Assert(inMaps(x)); - d_lowerConstraint.set(x,constraint); + Assert(greaterThanLowerBound(x, c->getValue())); + d_lbc.set(x, c); } -void ArithPartialModel::setUpperConstraint(ArithVar x, TNode constraint){ - Debug("partial_model") << "setUpperConstraint(" - << x << ":" << constraint << ")" << endl; - Assert(inMaps(x)); - d_upperConstraint.set(x, constraint); -} +void ArithPartialModel::setUpperBoundConstraint(Constraint c){ + AssertArgument(c != NullConstraint, "Cannot set a upper bound to NullConstraint."); + AssertArgument(c->isEquality() || c->isUpperBound(), + "Constraint type must be set to an equality or UpperBound."); -TNode ArithPartialModel::getLowerConstraint(ArithVar x){ + ArithVar x = c->getVariable(); + Debug("partial_model") << "setUpperBoundConstraint(" << x << ":" << c << ")" << endl; Assert(inMaps(x)); - Assert(hasLowerBound(x)); - return d_lowerConstraint[x]; -} + Assert(lessThanUpperBound(x, c->getValue())); -TNode ArithPartialModel::getUpperConstraint(ArithVar x){ - Assert(inMaps(x)); - Assert(hasUpperBound(x)); - return d_upperConstraint[x]; + d_ubc.set(x, c); } -int ArithPartialModel::cmpToLowerBound(ArithVar x, const DeltaRational& c){ +int ArithPartialModel::cmpToLowerBound(ArithVar x, const DeltaRational& c) const{ if(!hasLowerBound(x)){ // l = -\intfy // ? c < -\infty |- _|_ return 1; }else{ - return c.cmp(d_lowerBound[x]); + return c.cmp(getLowerBound(x)); } } -int ArithPartialModel::cmpToUpperBound(ArithVar x, const DeltaRational& c){ +int ArithPartialModel::cmpToUpperBound(ArithVar x, const DeltaRational& c) const{ if(!hasUpperBound(x)){ //u = \intfy // ? c > \infty |- _|_ return -1; }else{ - return c.cmp(d_upperBound[x]); + return c.cmp(getUpperBound(x)); } } -// bool ArithPartialModel::belowLowerBound(ArithVar x, const DeltaRational& c, bool strict){ -// if(!hasLowerBound(x)){ -// // l = -\intfy -// // ? c < -\infty |- _|_ -// return false; -// } -// if(strict){ -// return c < d_lowerBound[x]; -// }else{ -// return c <= d_lowerBound[x]; -// } -// } - -// bool ArithPartialModel::aboveUpperBound(ArithVar x, const DeltaRational& c, bool strict){ -// if(!hasUpperBound(x)){ -// // u = \intfy -// // ? c > \infty |- _|_ -// return false; -// } -// if(strict){ -// return c > d_upperBound[x]; -// }else{ -// return c >= d_upperBound[x]; -// } -// } - bool ArithPartialModel::equalsLowerBound(ArithVar x, const DeltaRational& c){ if(!hasLowerBound(x)){ return false; }else{ - return c == d_lowerBound[x]; + return c == getLowerBound(x); } } bool ArithPartialModel::equalsUpperBound(ArithVar x, const DeltaRational& c){ if(!hasUpperBound(x)){ return false; }else{ - return c == d_upperBound[x]; + return c == getUpperBound(x); } } -bool ArithPartialModel::hasEitherBound(ArithVar x){ +bool ArithPartialModel::hasEitherBound(ArithVar x) const{ return hasLowerBound(x) || hasUpperBound(x); } -bool ArithPartialModel::strictlyBelowUpperBound(ArithVar x){ +bool ArithPartialModel::strictlyBelowUpperBound(ArithVar x) const{ Assert(inMaps(x)); if(!hasUpperBound(x)){ // u = \infty return true; + }else{ + return d_assignment[x] < getUpperBound(x); } - return d_assignment[x] < d_upperBound[x]; } -bool ArithPartialModel::strictlyAboveLowerBound(ArithVar x){ +bool ArithPartialModel::strictlyAboveLowerBound(ArithVar x) const{ Assert(inMaps(x)); if(!hasLowerBound(x)){ // l = -\infty return true; + }else{ + return getLowerBound(x) < d_assignment[x]; } - return d_lowerBound[x] < d_assignment[x]; } -// /** -// * x <= u -// * ? c < u -// */ -// bool ArithPartialModel::strictlyBelowUpperBound(ArithVar x, const DeltaRational& c){ -// Assert(inMaps(x)); -// if(!hasUpperBound(x)){ // u = \infty -// return true; -// } -// return c < d_upperBound[x]; -// } - -// /** -// * x <= u -// * ? c < u -// */ -// bool ArithPartialModel::strictlyAboveLowerBound(ArithVar x, const DeltaRational& c){ -// Assert(inMaps(x)); -// if(!hasLowerBound(x)){ // l = -\infty -// return true; -// } -// return d_lowerBound[x] < c; -// } - -bool ArithPartialModel::assignmentIsConsistent(ArithVar x){ +bool ArithPartialModel::assignmentIsConsistent(ArithVar x) const{ const DeltaRational& beta = getAssignment(x); //l_i <= beta(x_i) <= u_i - return cmpToLowerBound(x,beta) >= 0 && cmpToUpperBound(x,beta) <= 0; + return greaterThanLowerBound(x,beta) && lessThanUpperBound(x,beta); } @@ -355,13 +261,13 @@ void ArithPartialModel::printModel(ArithVar x){ Debug("model") << "no lb "; }else{ Debug("model") << getLowerBound(x) << " "; - Debug("model") << getLowerConstraint(x) << " "; + Debug("model") << getLowerBoundConstraint(x) << " "; } if(!hasUpperBound(x)){ Debug("model") << "no ub "; }else{ Debug("model") << getUpperBound(x) << " "; - Debug("model") << getUpperConstraint(x) << " "; + Debug("model") << getUpperBoundConstraint(x) << " "; } } diff --git a/src/theory/arith/partial_model.h b/src/theory/arith/partial_model.h index 7e2211595..fc8423e36 100644 --- a/src/theory/arith/partial_model.h +++ b/src/theory/arith/partial_model.h @@ -19,16 +19,18 @@ #include "cvc4_private.h" +#include "expr/node.h" + #include "context/context.h" #include "context/cdvector.h" +#include "context/cdo.h" + #include "theory/arith/arithvar.h" #include "theory/arith/delta_rational.h" -#include "expr/attribute.h" -#include "expr/node.h" +#include "theory/arith/constraint_forward.h" -#include "theory/arith/difference_manager.h" -#include <deque> +#include <vector> #ifndef __CVC4__THEORY__ARITH__PARTIAL_MODEL_H #define __CVC4__THEORY__ARITH__PARTIAL_MODEL_H @@ -41,19 +43,14 @@ class ArithPartialModel { private: unsigned d_mapSize; - //Maps from ArithVar -> T - - std::vector<bool> d_hasHadABound; + //Maps from ArithVar -> T std::vector<bool> d_hasSafeAssignment; std::vector<DeltaRational> d_assignment; std::vector<DeltaRational> d_safeAssignment; - context::CDVector<DeltaRational> d_upperBound; - context::CDVector<DeltaRational> d_lowerBound; - context::CDVector<Node> d_upperConstraint; - context::CDVector<Node> d_lowerConstraint; - + context::CDVector<Constraint> d_ubc; + context::CDVector<Constraint> d_lbc; bool d_deltaIsSafe; Rational d_delta; @@ -64,30 +61,20 @@ private: typedef std::vector<ArithVar> HistoryList; HistoryList d_history; - DifferenceManager& d_dm; public: - ArithPartialModel(context::Context* c, DifferenceManager& dm): - d_mapSize(0), - d_hasHadABound(), - d_hasSafeAssignment(), - d_assignment(), - d_safeAssignment(), - d_upperBound(c), - d_lowerBound(c), - d_upperConstraint(c), - d_lowerConstraint(c), - d_deltaIsSafe(false), - d_delta(-1,1), - d_history(), - d_dm(dm) - { } - - void setLowerConstraint(ArithVar x, TNode constraint); - void setUpperConstraint(ArithVar x, TNode constraint); - TNode getLowerConstraint(ArithVar x); - TNode getUpperConstraint(ArithVar x); + ArithPartialModel(context::Context* c); + + void setLowerBoundConstraint(Constraint lb); + void setUpperBoundConstraint(Constraint ub); + + inline Constraint getUpperBoundConstraint(ArithVar x) const{ + return d_ubc[x]; + } + inline Constraint getLowerBoundConstraint(ArithVar x) const{ + return d_lbc[x]; + } /* Initializes a variable to a safe value.*/ @@ -112,14 +99,7 @@ public: return hasUpperBound(x) && getUpperBound(x).sgn() == 0; } -private: - void zeroDifferenceDetected(ArithVar x); - -public: - bool boundsAreEqual(ArithVar x); - - void setUpperBound(ArithVar x, const DeltaRational& r); - void setLowerBound(ArithVar x, const DeltaRational& r); + bool boundsAreEqual(ArithVar x) const; /* Sets an unsafe variable assignment */ void setAssignment(ArithVar x, const DeltaRational& r); @@ -127,8 +107,8 @@ public: /** Must know that the bound exists before calling this! */ - const DeltaRational& getUpperBound(ArithVar x); - const DeltaRational& getLowerBound(ArithVar x); + const DeltaRational& getUpperBound(ArithVar x) const; + const DeltaRational& getLowerBound(ArithVar x) const; const DeltaRational& getAssignment(ArithVar x) const; @@ -141,61 +121,60 @@ public: * If lowerbound = - \infty: * return 1 */ - int cmpToLowerBound(ArithVar x, const DeltaRational& c); + int cmpToLowerBound(ArithVar x, const DeltaRational& c) const; - inline bool strictlyLessThanLowerBound(ArithVar x, const DeltaRational& c){ + inline bool strictlyLessThanLowerBound(ArithVar x, const DeltaRational& c) const{ return cmpToLowerBound(x, c) < 0; } - inline bool lessThanLowerBound(ArithVar x, const DeltaRational& c){ + inline bool lessThanLowerBound(ArithVar x, const DeltaRational& c) const{ return cmpToLowerBound(x, c) <= 0; } - inline bool strictlyGreaterThanLowerBound(ArithVar x, const DeltaRational& c){ + inline bool strictlyGreaterThanLowerBound(ArithVar x, const DeltaRational& c) const{ return cmpToLowerBound(x, c) > 0; } + inline bool greaterThanLowerBound(ArithVar x, const DeltaRational& c) const{ + return cmpToLowerBound(x, c) >= 0; + } /** * If upperbound < \infty: * return getAssignment(x).cmp(getUpperBound(x)) * If upperbound = \infty: * return -1 */ - int cmpToUpperBound(ArithVar x, const DeltaRational& c); + int cmpToUpperBound(ArithVar x, const DeltaRational& c) const; - inline bool strictlyLessThanUpperBound(ArithVar x, const DeltaRational& c){ + inline bool strictlyLessThanUpperBound(ArithVar x, const DeltaRational& c) const{ return cmpToUpperBound(x, c) < 0; } - inline bool lessThanUpperBound(ArithVar x, const DeltaRational& c){ + inline bool lessThanUpperBound(ArithVar x, const DeltaRational& c) const{ return cmpToUpperBound(x, c) <= 0; } - inline bool strictlyGreaterThanUpperBound(ArithVar x, const DeltaRational& c){ + inline bool strictlyGreaterThanUpperBound(ArithVar x, const DeltaRational& c) const{ return cmpToUpperBound(x, c) > 0; } - inline bool greaterThanUpperBound(ArithVar x, const DeltaRational& c){ + inline bool greaterThanUpperBound(ArithVar x, const DeltaRational& c) const{ return cmpToUpperBound(x, c) >= 0; } - bool strictlyBelowUpperBound(ArithVar x); - bool strictlyAboveLowerBound(ArithVar x); - bool assignmentIsConsistent(ArithVar x); + bool strictlyBelowUpperBound(ArithVar x) const; + bool strictlyAboveLowerBound(ArithVar x) const; + bool assignmentIsConsistent(ArithVar x) const; void printModel(ArithVar x); /** returns true iff x has both a lower and upper bound. */ - bool hasEitherBound(ArithVar x); - inline bool hasLowerBound(ArithVar x){ - return !d_lowerConstraint[x].isNull(); + bool hasEitherBound(ArithVar x) const; + inline bool hasLowerBound(ArithVar x) const{ + return d_lbc[x] != NullConstraint; } - inline bool hasUpperBound(ArithVar x){ - return !d_upperConstraint[x].isNull(); - } - - bool hasEverHadABound(ArithVar var){ - return d_hasHadABound[var]; + inline bool hasUpperBound(ArithVar x) const{ + return d_ubc[x] != NullConstraint; } const Rational& getDelta(){ diff --git a/src/theory/arith/simplex.cpp b/src/theory/arith/simplex.cpp index 7fce748dc..5837d4793 100644 --- a/src/theory/arith/simplex.cpp +++ b/src/theory/arith/simplex.cpp @@ -33,15 +33,13 @@ static const uint32_t NUM_CHECKS = 10; static const bool CHECK_AFTER_PIVOT = true; static const uint32_t VARORDER_CHECK_PERIOD = 200; -SimplexDecisionProcedure::SimplexDecisionProcedure(ArithPropManager& propManager, - LinearEqualityModule& linEq) : +SimplexDecisionProcedure::SimplexDecisionProcedure(LinearEqualityModule& linEq, NodeCallBack& conflictChannel) : d_linEq(linEq), d_partialModel(d_linEq.getPartialModel()), d_tableau(d_linEq.getTableau()), d_queue(d_partialModel, d_tableau), - d_propManager(propManager), d_numVariables(0), - d_delayedLemmas(), + d_conflictChannel(conflictChannel), d_pivotsInRound(), d_DELTA_ZERO(0,0) { @@ -77,7 +75,7 @@ SimplexDecisionProcedure::Statistics::Statistics(): d_weakeningSuccesses("theory::arith::weakening::success",0), d_weakenings("theory::arith::weakening::total",0), d_weakenTime("theory::arith::weakening::time"), - d_delayedConflicts("theory::arith::delayedConflicts",0) + d_simplexConflicts("theory::arith::simplexConflicts",0) { StatisticsRegistry::registerStat(&d_statUpdateConflicts); @@ -99,7 +97,7 @@ SimplexDecisionProcedure::Statistics::Statistics(): StatisticsRegistry::registerStat(&d_weakenings); StatisticsRegistry::registerStat(&d_weakenTime); - StatisticsRegistry::registerStat(&d_delayedConflicts); + StatisticsRegistry::registerStat(&d_simplexConflicts); } SimplexDecisionProcedure::Statistics::~Statistics(){ @@ -123,7 +121,7 @@ SimplexDecisionProcedure::Statistics::~Statistics(){ StatisticsRegistry::unregisterStat(&d_weakenings); StatisticsRegistry::unregisterStat(&d_weakenTime); - StatisticsRegistry::unregisterStat(&d_delayedConflicts); + StatisticsRegistry::unregisterStat(&d_simplexConflicts); } @@ -203,7 +201,7 @@ Node betterConflict(TNode x, TNode y){ else return y; } -Node SimplexDecisionProcedure::findConflictOnTheQueue(SearchPeriod type, bool returnFirst) { +bool SimplexDecisionProcedure::findConflictOnTheQueue(SearchPeriod type) { TimerStat::CodeTimer codeTimer(d_statistics.d_findConflictOnTheQueueTime); switch(type){ @@ -215,7 +213,6 @@ Node SimplexDecisionProcedure::findConflictOnTheQueue(SearchPeriod type, bool re } bool success = false; - Node firstConflict = Node::null(); ArithPriorityQueue::const_iterator i = d_queue.begin(); ArithPriorityQueue::const_iterator end = d_queue.end(); for(; i != end; ++i){ @@ -225,11 +222,7 @@ Node SimplexDecisionProcedure::findConflictOnTheQueue(SearchPeriod type, bool re Node possibleConflict = checkBasicForConflict(x_i); if(!possibleConflict.isNull()){ success = true; - if(returnFirst && firstConflict.isNull()){ - firstConflict = possibleConflict; - }else{ - delayConflictAsLemma(possibleConflict); - } + reportConflict(possibleConflict); } } } @@ -242,13 +235,14 @@ Node SimplexDecisionProcedure::findConflictOnTheQueue(SearchPeriod type, bool re case AfterVarOrderSearch: ++(d_statistics.d_successAfterVarOrderSearch); break; } } - return firstConflict; + return success; } -Node SimplexDecisionProcedure::findModel(){ +bool SimplexDecisionProcedure::findModel(){ if(d_queue.empty()){ - return Node::null(); + return false; } + bool foundConflict = false; static CVC4_THREADLOCAL(unsigned int) instance = 0; instance = instance + 1; @@ -256,45 +250,44 @@ Node SimplexDecisionProcedure::findModel(){ d_queue.transitionToDifferenceMode(); - Node possibleConflict = Node::null(); if(d_queue.size() > 1){ - possibleConflict = findConflictOnTheQueue(BeforeDiffSearch); + foundConflict = findConflictOnTheQueue(BeforeDiffSearch); } - if(possibleConflict.isNull()){ + if(!foundConflict){ uint32_t numHueristicPivots = d_numVariables + 1; uint32_t pivotsRemaining = numHueristicPivots; uint32_t pivotsPerCheck = (numHueristicPivots/NUM_CHECKS) + (NUM_CHECKS-1); while(!d_queue.empty() && - possibleConflict.isNull() && + !foundConflict && pivotsRemaining > 0){ uint32_t pivotsToDo = min(pivotsPerCheck, pivotsRemaining); - possibleConflict = searchForFeasibleSolution(pivotsToDo); + foundConflict = searchForFeasibleSolution(pivotsToDo); pivotsRemaining -= pivotsToDo; //Once every CHECK_PERIOD examine the entire queue for conflicts - if(possibleConflict.isNull()){ - possibleConflict = findConflictOnTheQueue(DuringDiffSearch); + if(!foundConflict){ + foundConflict = findConflictOnTheQueue(DuringDiffSearch); }else{ - findConflictOnTheQueue(AfterDiffSearch, false); + findConflictOnTheQueue(AfterDiffSearch); } } } - if(!d_queue.empty() && possibleConflict.isNull()){ + if(!d_queue.empty() && !foundConflict){ d_queue.transitionToVariableOrderMode(); - while(!d_queue.empty() && possibleConflict.isNull()){ - possibleConflict = searchForFeasibleSolution(VARORDER_CHECK_PERIOD); + while(!d_queue.empty() && !foundConflict){ + foundConflict = searchForFeasibleSolution(VARORDER_CHECK_PERIOD); //Once every CHECK_PERIOD examine the entire queue for conflicts - if(possibleConflict.isNull()){ - possibleConflict = findConflictOnTheQueue(DuringVarOrderSearch); - }else{ - findConflictOnTheQueue(AfterVarOrderSearch, false); + if(!foundConflict){ + foundConflict = findConflictOnTheQueue(DuringVarOrderSearch); + } else{ + findConflictOnTheQueue(AfterVarOrderSearch); } } } - Assert(!possibleConflict.isNull() || d_queue.empty()); + Assert(foundConflict || d_queue.empty()); // Curiously the invariant that we always do a full check // means that the assignment we can always empty these queues. @@ -309,7 +302,7 @@ Node SimplexDecisionProcedure::findModel(){ Debug("arith::findModel") << "end findModel() " << instance << endl; - return possibleConflict; + return foundConflict; } Node SimplexDecisionProcedure::checkBasicForConflict(ArithVar basic){ @@ -333,7 +326,7 @@ Node SimplexDecisionProcedure::checkBasicForConflict(ArithVar basic){ //corresponds to Check() in dM06 //template <SimplexDecisionProcedure::PreferenceFunction pf> -Node SimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingIterations){ +bool SimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingIterations){ Debug("arith") << "searchForFeasibleSolution" << endl; Assert(remainingIterations > 0); @@ -344,7 +337,7 @@ Node SimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingItera Debug("arith::update::select") << "selectSmallestInconsistentVar()=" << x_i << endl; if(x_i == ARITHVAR_SENTINEL){ Debug("arith_update") << "No inconsistent variables" << endl; - return Node::null(); //sat + return false; //sat } --remainingIterations; @@ -369,7 +362,9 @@ Node SimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingItera x_j = selectSlackUpperBound(x_i, pf); if(x_j == ARITHVAR_SENTINEL ){ ++(d_statistics.d_statUpdateConflicts); - return generateConflictBelowLowerBound(x_i); //unsat + Node conflict = generateConflictBelowLowerBound(x_i); //unsat + reportConflict(conflict); + return true; } DeltaRational l_i = d_partialModel.getLowerBound(x_i); d_linEq.pivotAndUpdate(x_i, x_j, l_i); @@ -378,7 +373,9 @@ Node SimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingItera x_j = selectSlackLowerBound(x_i, pf); if(x_j == ARITHVAR_SENTINEL ){ ++(d_statistics.d_statUpdateConflicts); - return generateConflictAboveUpperBound(x_i); //unsat + Node conflict = generateConflictAboveUpperBound(x_i); //unsat + reportConflict(conflict); + return true; } DeltaRational u_i = d_partialModel.getUpperBound(x_i); d_linEq.pivotAndUpdate(x_i, x_j, u_i); @@ -389,38 +386,50 @@ Node SimplexDecisionProcedure::searchForFeasibleSolution(uint32_t remainingItera if(CHECK_AFTER_PIVOT){ Node possibleConflict = checkBasicForConflict(x_j); if(!possibleConflict.isNull()){ - return possibleConflict; + reportConflict(possibleConflict); + return true; // unsat } } } Assert(remainingIterations == 0); - return Node::null(); + return false; } -TNode SimplexDecisionProcedure::weakestExplanation(bool aboveUpper, DeltaRational& surplus, ArithVar v, const Rational& coeff, bool& anyWeakening, ArithVar basic){ +Constraint SimplexDecisionProcedure::weakestExplanation(bool aboveUpper, DeltaRational& surplus, ArithVar v, const Rational& coeff, bool& anyWeakening, ArithVar basic){ int sgn = coeff.sgn(); bool ub = aboveUpper?(sgn < 0) : (sgn > 0); - TNode exp = ub ? - d_partialModel.getUpperConstraint(v) : - d_partialModel.getLowerConstraint(v); - DeltaRational bound = ub? - d_partialModel.getUpperBound(v) : - d_partialModel.getLowerBound(v); + + Constraint c = ub ? + d_partialModel.getUpperBoundConstraint(v) : + d_partialModel.getLowerBoundConstraint(v); + +// #warning "revisit" +// Node exp = ub ? +// d_partialModel.explainUpperBound(v) : +// d_partialModel.explainLowerBound(v); bool weakened; do{ + const DeltaRational& bound = c->getValue(); + weakened = false; - Node weaker = ub? - d_propManager.strictlyWeakerAssertedUpperBound(v, bound): - d_propManager.strictlyWeakerAssertedLowerBound(v, bound); + Constraint weaker = ub? + c->getStrictlyWeakerUpperBound(true, true): + c->getStrictlyWeakerLowerBound(true, true); + + // Node weaker = ub? + // d_propManager.strictlyWeakerAssertedUpperBound(v, bound): + // d_propManager.strictlyWeakerAssertedLowerBound(v, bound); - if(!weaker.isNull()){ - DeltaRational weakerBound = asDeltaRational(weaker); + if(weaker != NullConstraint){ + //if(!weaker.isNull()){ + const DeltaRational& weakerBound = weaker->getValue(); + //DeltaRational weakerBound = asDeltaRational(weaker); DeltaRational diff = aboveUpper ? bound - weakerBound : weakerBound - bound; //if var == basic, @@ -438,24 +447,16 @@ TNode SimplexDecisionProcedure::weakestExplanation(bool aboveUpper, DeltaRationa Debug("weak") << " basic: "; } Debug("weak") << " " << surplus << " "<< diff << endl - << " " << bound << exp << endl + << " " << bound << c << endl << " " << weakerBound << weaker << endl; - if(exp.getKind() == AND){ - Debug("weak") << "VICTORY" << endl; - } - Assert(diff > d_DELTA_ZERO); - exp = weaker; - bound = weakerBound; + c = weaker; } } }while(weakened); - if(exp.getKind() == AND){ - Debug("weak") << "boo: " << exp << endl; - } - return exp; + return c; } Node SimplexDecisionProcedure::weakenConflict(bool aboveUpper, ArithVar basicVar){ @@ -479,7 +480,15 @@ Node SimplexDecisionProcedure::weakenConflict(bool aboveUpper, ArithVar basicVar const TableauEntry& entry = *i; ArithVar v = entry.getColVar(); const Rational& coeff = entry.getCoefficient(); - conflict << weakestExplanation(aboveUpper, surplus, v, coeff, anyWeakenings, basicVar); + bool weakening = false; + Constraint c = weakestExplanation(aboveUpper, surplus, v, coeff, weakening, basicVar); + Debug("weak") << "weak : " << weakening << " " << c->assertedToTheTheory() + << c << endl + << c->explainForConflict() << endl; + anyWeakenings = anyWeakenings || weakening; + + Debug("weak") << "weak : " << c->explainForConflict() << endl; + c->explainForConflict(conflict); } ++d_statistics.d_weakeningAttempts; if(anyWeakenings){ diff --git a/src/theory/arith/simplex.h b/src/theory/arith/simplex.h index 39c0bc20b..4e5ba3d9e 100644 --- a/src/theory/arith/simplex.h +++ b/src/theory/arith/simplex.h @@ -56,11 +56,11 @@ #include "theory/arith/delta_rational.h" #include "theory/arith/tableau.h" #include "theory/arith/partial_model.h" -#include "theory/arith/arith_prop_manager.h" #include "theory/arith/linear_equality.h" -#include "util/options.h" +#include "context/cdlist.h" +#include "util/options.h" #include "util/stats.h" #include <queue> @@ -91,13 +91,11 @@ private: /** Contains a superset of the basic variables in violation of their bounds. */ ArithPriorityQueue d_queue; - /** A link to the propagation manager. This is used to generate weaker conflicts. */ - ArithPropManager& d_propManager; - /** Number of variables in the system. This is used for tuning heuristics. */ ArithVar d_numVariables; - std::queue<Node> d_delayedLemmas; + /** This is the call back channel for Simplex to report conflicts. */ + NodeCallBack& d_conflictChannel; /** Maps a variable to how many times they have been used as a pivot in the simplex search. */ ArithVarMultiset d_pivotsInRound; @@ -106,8 +104,7 @@ private: DeltaRational d_DELTA_ZERO; public: - SimplexDecisionProcedure(ArithPropManager& propManager, - LinearEqualityModule& linEq); + SimplexDecisionProcedure(LinearEqualityModule& linEq, NodeCallBack& conflictChannel); /** * This must be called when the value of a basic variable may now voilate one @@ -123,14 +120,15 @@ public: * This is done by a simplex search through the possible bases of the tableau. * * If all of the variables can be made consistent with their bounds - * Node::null() is returned. Otherwise a minimized conflict is returned. + * false is returned. Otherwise true is returned, and at least 1 conflict + * was reported on the conflictCallback passed to the Module. * * Tableau pivoting is performed so variables may switch from being basic to * nonbasic and vice versa. * * Corresponds to the "check()" procedure in [Cav06]. */ - Node findModel(); + bool findModel(); private: @@ -158,6 +156,7 @@ private: * during the VarOrder stage of findModel. */ static ArithVar minColLength(const SimplexDecisionProcedure& simp, ArithVar x, ArithVar y); + /** * minBoundAndRowCount is a PreferenceFunction for preferring a variable * without an asserted bound over variables with an asserted bound. @@ -173,11 +172,11 @@ private: private: - Node searchForFeasibleSolution(uint32_t maxIterations); + bool searchForFeasibleSolution(uint32_t maxIterations); enum SearchPeriod {BeforeDiffSearch, DuringDiffSearch, AfterDiffSearch, DuringVarOrderSearch, AfterVarOrderSearch}; - Node findConflictOnTheQueue(SearchPeriod period, bool returnFirst = true); + bool findConflictOnTheQueue(SearchPeriod period); /** @@ -217,29 +216,12 @@ private: public: void increaseMax() {d_numVariables++;} - /** Returns true if the simplex procedure has more delayed lemmas in its queue.*/ - bool hasMoreLemmas() const { - return !d_delayedLemmas.empty(); - } - /** Returns the next delayed lemmas on the queue.*/ - Node popLemma(){ - Assert(hasMoreLemmas()); - Node lemma = d_delayedLemmas.front(); - d_delayedLemmas.pop(); - return lemma; - } - private: - /** Adds a lemma to the queue. */ - void pushLemma(Node lemma){ - d_delayedLemmas.push(lemma); - ++(d_statistics.d_delayedConflicts); - } - /** Adds a conflict as a lemma to the queue. */ - void delayConflictAsLemma(Node conflict){ - Node negatedConflict = negateConjunctionAsClause(conflict); - pushLemma(negatedConflict); + /** Reports a conflict to on the output channel. */ + void reportConflict(Node conflict){ + d_conflictChannel(conflict); + ++(d_statistics.d_simplexConflicts); } template <bool above> @@ -259,7 +241,7 @@ private: Node checkBasicForConflict(ArithVar b); Node weakenConflict(bool aboveUpper, ArithVar basicVar); - TNode weakestExplanation(bool aboveUpper, DeltaRational& surplus, ArithVar v, const Rational& coeff, bool& anyWeakening, ArithVar basic); + Constraint weakestExplanation(bool aboveUpper, DeltaRational& surplus, ArithVar v, const Rational& coeff, bool& anyWeakening, ArithVar basic); @@ -280,7 +262,7 @@ private: TimerStat d_weakenTime; - IntStat d_delayedConflicts; + IntStat d_simplexConflicts; Statistics(); ~Statistics(); diff --git a/src/theory/arith/tableau.cpp b/src/theory/arith/tableau.cpp index ef3206650..567d8215e 100644 --- a/src/theory/arith/tableau.cpp +++ b/src/theory/arith/tableau.cpp @@ -78,7 +78,6 @@ void Tableau::pivot(ArithVar oldBasic, ArithVar newBasic){ Assert(!isBasic(newBasic)); Assert(mergeBufferIsEmpty()); - //cout << oldBasic << "," << newBasic << endl; Debug("tableau") << "Tableau::pivot(" << oldBasic <<", " << newBasic <<")" << endl; rowPivot(oldBasic, newBasic); diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp index 3b29cbcd1..11a1a4a4a 100644 --- a/src/theory/arith/theory_arith.cpp +++ b/src/theory/arith/theory_arith.cpp @@ -23,14 +23,13 @@ #include "expr/node_builder.h" #include "theory/valuation.h" +#include "theory/rewriter.h" #include "util/rational.h" #include "util/integer.h" #include "util/boolean_simplification.h" -#include "theory/rewriter.h" - #include "theory/arith/arith_utilities.h" #include "theory/arith/delta_rational.h" #include "theory/arith/partial_model.h" @@ -38,11 +37,9 @@ #include "theory/arith/arithvar_set.h" #include "theory/arith/arith_rewriter.h" -#include "theory/arith/atom_database.h" - +#include "theory/arith/constraint.h" #include "theory/arith/theory_arith.h" #include "theory/arith/normal_form.h" -#include "theory/arith/arith_prop_manager.h" #include <stdint.h> @@ -59,12 +56,12 @@ const uint32_t RESET_START = 2; TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation) : Theory(THEORY_ARITH, c, u, out, valuation), d_hasDoneWorkSinceCut(false), - d_atomsInContext(c), d_learner(d_pbSubstitutions), + d_setupLiteralCallback(this), d_nextIntegerCheckVar(0), d_constantIntegerVariables(c), - d_diseq(c), - d_partialModel(c, d_differenceManager), + d_diseqQueue(c, false), + d_partialModel(c), d_tableau(), d_linEq(d_partialModel, d_tableau, d_basicVarModelUpdateCallBack), d_diosolver(c), @@ -73,10 +70,11 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha d_rowHasBeenAdded(false), d_tableauResetDensity(1.6), d_tableauResetPeriod(10), - d_atomDatabase(c, out), - d_propManager(c, d_arithvarNodeMap, d_atomDatabase, valuation), - d_differenceManager(c, d_propManager), - d_simplex(d_propManager, d_linEq), + d_conflicts(c), + d_conflictCallBack(d_conflicts), + d_differenceManager(c, d_constraintDatabase, d_setupLiteralCallback), + d_simplex(d_linEq, d_conflictCallBack), + d_constraintDatabase(c, u, d_arithvarNodeMap, d_differenceManager), d_basicVarModelUpdateCallBack(d_simplex), d_DELTA_ZERO(0), d_statistics() @@ -152,13 +150,34 @@ TheoryArith::Statistics::~Statistics(){ StatisticsRegistry::unregisterStat(&d_boundPropagations); } +void TheoryArith::zeroDifferenceDetected(ArithVar x){ + Assert(d_differenceManager.isDifferenceSlack(x)); + Assert(d_partialModel.upperBoundIsZero(x)); + Assert(d_partialModel.lowerBoundIsZero(x)); + + Constraint lb = d_partialModel.getLowerBoundConstraint(x); + Constraint ub = d_partialModel.getUpperBoundConstraint(x); + + if(lb->isEquality()){ + d_differenceManager.differenceIsZero(lb); + }else if(ub->isEquality()){ + d_differenceManager.differenceIsZero(ub); + }else{ + d_differenceManager.differenceIsZero(lb, ub); + } +} + /* procedure AssertLower( x_i >= c_i ) */ -Node TheoryArith::AssertLower(ArithVar x_i, DeltaRational& c_i, TNode original){ +Node TheoryArith::AssertLower(Constraint constraint){ + Assert(constraint != NullConstraint); + Assert(constraint->isLowerBound()); + + ArithVar x_i = constraint->getVariable(); + const DeltaRational& c_i = constraint->getValue(); + Debug("arith") << "AssertLower(" << x_i << " " << c_i << ")"<< std::endl; - if(isInteger(x_i)){ - c_i = DeltaRational(c_i.ceiling()); - } + Assert(!isInteger(x_i) || c_i.isIntegral()); //TODO Relax to less than? if(d_partialModel.lessThanLowerBound(x_i, c_i)){ @@ -167,9 +186,8 @@ Node TheoryArith::AssertLower(ArithVar x_i, DeltaRational& c_i, TNode original){ int cmpToUB = d_partialModel.cmpToUpperBound(x_i, c_i); if(cmpToUB > 0){ // c_i < \lowerbound(x_i) - Node ubc = d_partialModel.getUpperConstraint(x_i); - Node conflict = NodeManager::currentNM()->mkNode(AND, ubc, original); - //d_out->conflict(conflict); + Constraint ubc = d_partialModel.getUpperBoundConstraint(x_i); + Node conflict = ConstraintValue::explainConflict(ubc, constraint); Debug("arith") << "AssertLower conflict " << conflict << endl; ++(d_statistics.d_statAssertLowerConflicts); return conflict; @@ -177,22 +195,36 @@ Node TheoryArith::AssertLower(ArithVar x_i, DeltaRational& c_i, TNode original){ if(isInteger(x_i)){ d_constantIntegerVariables.push_back(x_i); } - //check to make sure x_i != c_i has not been asserted - Node left = d_arithvarNodeMap.asNode(x_i); - // if lowerbound and upperbound are equal, then the infinitesimal must be 0 - Assert(c_i.getInfinitesimalPart().isZero()); - Node right = mkRationalNode(c_i.getNoninfinitesimalPart()); - - Node diseq = left.eqNode(right).notNode(); - if (d_diseq.find(diseq) != d_diseq.end()) { - Node ub = d_partialModel.getUpperConstraint(x_i); - return disequalityConflict(diseq, ub , original); + const ValueCollection& vc = constraint->getValueCollection(); + if(vc.hasDisequality()){ + Assert(vc.hasEquality()); + const Constraint eq = vc.getEquality(); + const Constraint diseq = vc.getDisequality(); + if(diseq->isTrue()){ + const Constraint ub = vc.getUpperBound(); + Node conflict = ConstraintValue::explainConflict(diseq, ub, constraint); + + ++(d_statistics.d_statDisequalityConflicts); + Debug("eq") << " assert lower conflict " << conflict << endl; + return conflict; + }else if(!eq->isTrue()){ + Debug("eq") << "lb == ub, propagate eq" << eq << endl; + eq->impliedBy(constraint, d_partialModel.getUpperBoundConstraint(x_i)); + } } } - d_partialModel.setLowerConstraint(x_i,original); - d_partialModel.setLowerBound(x_i, c_i); + d_partialModel.setLowerBoundConstraint(constraint); + + if(d_differenceManager.isDifferenceSlack(x_i)){ + int sgn = c_i.sgn(); + if(sgn > 0){ + d_differenceManager.differenceCannotBeZero(constraint); + }else if(sgn == 0 && d_partialModel.upperBoundIsZero(x_i)){ + zeroDifferenceDetected(x_i); + } + } d_updatedBounds.softAdd(x_i); @@ -210,12 +242,18 @@ Node TheoryArith::AssertLower(ArithVar x_i, DeltaRational& c_i, TNode original){ } /* procedure AssertUpper( x_i <= c_i) */ -Node TheoryArith::AssertUpper(ArithVar x_i, DeltaRational& c_i, TNode original){ +Node TheoryArith::AssertUpper(Constraint constraint){ + ArithVar x_i = constraint->getVariable(); + const DeltaRational& c_i = constraint->getValue(); + Debug("arith") << "AssertUpper(" << x_i << " " << c_i << ")"<< std::endl; + AssertArgument(constraint != NullConstraint, + "AssertUpper() called on a NullConstraint."); + Assert(constraint->isUpperBound()); - if(isInteger(x_i)){ - c_i = DeltaRational(c_i.floor()); - } + //Too strong because of rounding with integers + //Assert(!constraint->hasLiteral() || original == constraint->getLiteral()); + Assert(!isInteger(x_i) || c_i.isIntegral()); Debug("arith") << "AssertUpper(" << x_i << " " << c_i << ")"<< std::endl; @@ -226,8 +264,8 @@ Node TheoryArith::AssertUpper(ArithVar x_i, DeltaRational& c_i, TNode original){ // cmpToLb = \lowerbound(x_i).cmp(c_i) int cmpToLB = d_partialModel.cmpToLowerBound(x_i, c_i); if( cmpToLB < 0 ){ // \upperbound(x_i) < \lowerbound(x_i) - Node lbc = d_partialModel.getLowerConstraint(x_i); - Node conflict = NodeManager::currentNM()->mkNode(AND, lbc, original); + Constraint lbc = d_partialModel.getLowerBoundConstraint(x_i); + Node conflict = ConstraintValue::explainConflict(lbc, constraint); Debug("arith") << "AssertUpper conflict " << conflict << endl; ++(d_statistics.d_statAssertUpperConflicts); return conflict; @@ -236,22 +274,34 @@ Node TheoryArith::AssertUpper(ArithVar x_i, DeltaRational& c_i, TNode original){ d_constantIntegerVariables.push_back(x_i); } - //check to make sure x_i != c_i has not been asserted - Node left = d_arithvarNodeMap.asNode(x_i); - - // if lowerbound and upperbound are equal, then the infinitesimal must be 0 - Assert(c_i.getInfinitesimalPart().isZero()); - Node right = mkRationalNode(c_i.getNoninfinitesimalPart()); - - Node diseq = left.eqNode(right).notNode(); - if (d_diseq.find(diseq) != d_diseq.end()) { - Node lb = d_partialModel.getLowerConstraint(x_i); - return disequalityConflict(diseq, lb , original); + const ValueCollection& vc = constraint->getValueCollection(); + if(vc.hasDisequality()){ + Assert(vc.hasEquality()); + const Constraint diseq = vc.getDisequality(); + const Constraint eq = vc.getEquality(); + if(diseq->isTrue()){ + const Constraint lb = vc.getLowerBound(); + Node conflict = ConstraintValue::explainConflict(diseq, lb, constraint); + Debug("eq") << " assert upper conflict " << conflict << endl; + return conflict; + }else if(!eq->isTrue()){ + Debug("eq") << "lb == ub, propagate eq" << eq << endl; + eq->impliedBy(constraint, d_partialModel.getLowerBoundConstraint(x_i)); + } } + } - d_partialModel.setUpperConstraint(x_i,original); - d_partialModel.setUpperBound(x_i, c_i); + d_partialModel.setUpperBoundConstraint(constraint); + + if(d_differenceManager.isDifferenceSlack(x_i)){ + int sgn = c_i.sgn(); + if(sgn < 0){ + d_differenceManager.differenceCannotBeZero(constraint); + }else if(sgn == 0 && d_partialModel.lowerBoundIsZero(x_i)){ + zeroDifferenceDetected(x_i); + } + } d_updatedBounds.softAdd(x_i); @@ -269,11 +319,19 @@ Node TheoryArith::AssertUpper(ArithVar x_i, DeltaRational& c_i, TNode original){ } -/* procedure AssertLower( x_i == c_i ) */ -Node TheoryArith::AssertEquality(ArithVar x_i, DeltaRational& c_i, TNode original){ +/* procedure AssertEquality( x_i == c_i ) */ +Node TheoryArith::AssertEquality(Constraint constraint){ + AssertArgument(constraint != NullConstraint, + "AssertUpper() called on a NullConstraint."); + + ArithVar x_i = constraint->getVariable(); + const DeltaRational& c_i = constraint->getValue(); Debug("arith") << "AssertEquality(" << x_i << " " << c_i << ")"<< std::endl; + //Should be fine in integers + Assert(!isInteger(x_i) || c_i.isIntegral()); + int cmpToLB = d_partialModel.cmpToLowerBound(x_i, c_i); int cmpToUB = d_partialModel.cmpToUpperBound(x_i, c_i); @@ -284,16 +342,16 @@ Node TheoryArith::AssertEquality(ArithVar x_i, DeltaRational& c_i, TNode origina } if(cmpToUB > 0){ - Node ubc = d_partialModel.getUpperConstraint(x_i); - Node conflict = NodeManager::currentNM()->mkNode(AND, ubc, original); - Debug("arith") << "AssertLower conflict " << conflict << endl; + Constraint ubc = d_partialModel.getUpperBoundConstraint(x_i); + Node conflict = ConstraintValue::explainConflict(ubc, constraint); + Debug("arith") << "AssertEquality conflicts with upper bound " << conflict << endl; return conflict; } if(cmpToLB < 0){ - Node lbc = d_partialModel.getLowerConstraint(x_i); - Node conflict = NodeManager::currentNM()->mkNode(AND, lbc, original); - Debug("arith") << "AssertUpper conflict " << conflict << endl; + Constraint lbc = d_partialModel.getLowerBoundConstraint(x_i); + Node conflict = ConstraintValue::explainConflict(lbc, constraint); + Debug("arith") << "AssertEquality conflicts with lower bound" << conflict << endl; return conflict; } @@ -309,11 +367,17 @@ Node TheoryArith::AssertEquality(ArithVar x_i, DeltaRational& c_i, TNode origina // Don't bother to check whether x_i != c_i is in d_diseq // The a and (not a) should never be on the fact queue - d_partialModel.setLowerConstraint(x_i,original); - d_partialModel.setLowerBound(x_i, c_i); + d_partialModel.setUpperBoundConstraint(constraint); + d_partialModel.setLowerBoundConstraint(constraint); - d_partialModel.setUpperConstraint(x_i,original); - d_partialModel.setUpperBound(x_i, c_i); + if(d_differenceManager.isDifferenceSlack(x_i)){ + int sgn = c_i.sgn(); + if(sgn == 0){ + zeroDifferenceDetected(x_i); + }else{ + d_differenceManager.differenceCannotBeZero(constraint); + } + } d_updatedBounds.softAdd(x_i); @@ -329,6 +393,72 @@ Node TheoryArith::AssertEquality(ArithVar x_i, DeltaRational& c_i, TNode origina } +/* procedure AssertDisequality( x_i != c_i ) */ +Node TheoryArith::AssertDisequality(Constraint constraint){ + + AssertArgument(constraint != NullConstraint, + "AssertUpper() called on a NullConstraint."); + ArithVar x_i = constraint->getVariable(); + const DeltaRational& c_i = constraint->getValue(); + + Debug("arith") << "AssertDisequality(" << x_i << " " << c_i << ")"<< std::endl; + + //Should be fine in integers + Assert(!isInteger(x_i) || c_i.isIntegral()); + + if(d_differenceManager.isDifferenceSlack(x_i)){ + int sgn = c_i.sgn(); + if(sgn == 0){ + d_differenceManager.differenceCannotBeZero(constraint); + } + } + + if(constraint->isSplit()){ + Debug("eq") << "skipping already split " << constraint << endl; + return Node::null(); + } + + const ValueCollection& vc = constraint->getValueCollection(); + if(vc.hasLowerBound() && vc.hasUpperBound()){ + const Constraint lb = vc.getLowerBound(); + const Constraint ub = vc.getUpperBound(); + if(lb->isTrue() && ub->isTrue()){ + //in conflict + Debug("eq") << "explaining" << endl; + ++(d_statistics.d_statDisequalityConflicts); + return ConstraintValue::explainConflict(constraint, lb, ub); + }else if(lb->isTrue()){ + Debug("eq") << "propagate UpperBound " << constraint << lb << ub << endl; + const Constraint negUb = ub->getNegation(); + if(!negUb->isTrue()){ + negUb->impliedBy(constraint, lb); + } + }else if(ub->isTrue()){ + Debug("eq") << "propagate LowerBound " << constraint << lb << ub << endl; + const Constraint negLb = lb->getNegation(); + if(!negLb->isTrue()){ + negLb->impliedBy(constraint, ub); + } + } + } + + + if(c_i == d_partialModel.getAssignment(x_i)){ + Debug("eq") << "lemma now!" << endl; + d_out->lemma(constraint->split()); + return Node::null(); + }else if(d_partialModel.strictlyLessThanLowerBound(x_i, c_i)){ + Debug("eq") << "can drop as less than lb" << constraint << endl; + }else if(d_partialModel.strictlyGreaterThanUpperBound(x_i, c_i)){ + Debug("eq") << "can drop as less than ub" << constraint << endl; + }else{ + Debug("eq") << "push back" << constraint << endl; + d_diseqQueue.push(constraint); + } + return Node::null(); + +} + void TheoryArith::addSharedTerm(TNode n){ d_differenceManager.addSharedTerm(n); if(!n.isConst() && !isSetup(n)){ @@ -360,10 +490,11 @@ Node TheoryArith::ppRewrite(TNode atom) { Debug("pb") << "arith::preprocess() : after pb substitutions and rewriting: " << a << endl; Debug("arith::preprocess") << "arith::preprocess() :" - << "after pb substitutions and rewriting: " << a << endl; + << "after pb substitutions and rewriting: " + << a << endl; } - if (a.getKind() == kind::EQUAL) { + if (a.getKind() == kind::EQUAL && Options::current()->arithRewriteEq) { Node leq = NodeBuilder<2>(kind::LEQ) << a[0] << a[1]; Node geq = NodeBuilder<2>(kind::GEQ) << a[0] << a[1]; Node rewritten = Rewriter::rewrite(leq.andNode(geq)); @@ -383,44 +514,61 @@ Theory::PPAssertStatus TheoryArith::ppAssert(TNode in, SubstitutionMap& outSubst Rational minConstant = 0; Node minMonomial; Node minVar; - unsigned nVars = 0; if (in.getKind() == kind::EQUAL) { - Assert(in[1].getKind() == kind::CONST_RATIONAL); - // Find the variable with the smallest coefficient - Polynomial p = Polynomial::parsePolynomial(in[0]); - Polynomial::iterator it = p.begin(), it_end = p.end(); - for (; it != it_end; ++ it) { - Monomial m = *it; - // Skip the constant - if (m.isConstant()) continue; - // This is a ''variable'' - nVars ++; - // Skip the non-linear stuff - if (!m.getVarList().singleton()) continue; - // Get the minimal one - Rational constant = m.getConstant().getValue(); - Rational absSconstant = constant > 0 ? constant : -constant; - if (minVar.isNull() || absSconstant < minConstant) { - Node var = m.getVarList().getNode(); - if (var.getKind() == kind::VARIABLE) { - minVar = var; - minMonomial = m.getNode(); - minConstant = constant; - } + Comparison cmp = Comparison::parseNormalForm(in); + + Polynomial left = cmp.getLeft(); + Polynomial right = cmp.getRight(); + + Monomial m = left.getHead(); + if (m.getVarList().singleton()){ + VarList vl = m.getVarList(); + Node var = vl.getNode(); + if (var.getKind() == kind::VARIABLE && !vl.isIntegral()) { + minVar = var; } } + //Assert(in[1].getKind() == kind::CONST_RATIONAL); + // Find the variable with the smallest coefficient + //Polynomial p = Polynomial::parsePolynomial(in[0]); + + // Polynomial::iterator it = p.begin(), it_end = p.end(); + // for (; it != it_end; ++ it) { + // Monomial m = *it; + // // Skip the constant + // if (m.isConstant()) continue; + // // This is a ''variable'' + // nVars ++; + // // Skip the non-linear stuff + // if (!m.getVarList().singleton()) continue; + // // Get the minimal one + // Rational constant = m.getConstant().getValue(); + // Rational absSconstant = constant > 0 ? constant : -constant; + // if (minVar.isNull() || absSconstant < minConstant) { + // Node var = m.getVarList().getNode(); + // if (var.getKind() == kind::VARIABLE) { + // minVar = var; + // minMonomial = m.getNode(); + // minConstant = constant; + // } + // } + //} + // Solve for variable if (!minVar.isNull()) { + Polynomial right = cmp.getRight(); + Node eliminateVar = right.getNode(); // ax + p = c -> (ax + p) -ax - c = -ax - Node eliminateVar = NodeManager::currentNM()->mkNode(kind::MINUS, in[0], minMonomial); - if (in[1].getConst<Rational>() != 0) { - eliminateVar = NodeManager::currentNM()->mkNode(kind::MINUS, eliminateVar, in[1]); - } - // x = (p - ax - c) * -1/a - eliminateVar = NodeManager::currentNM()->mkNode(kind::MULT, eliminateVar, mkRationalNode(- minConstant.inverse())); - // Add the substitution if not recursive - Node rewritten = Rewriter::rewrite(eliminateVar); + // Node eliminateVar = NodeManager::currentNM()->mkNode(kind::MINUS, in[0], minMonomial); + // if (in[1].getConst<Rational>() != 0) { + // eliminateVar = NodeManager::currentNM()->mkNode(kind::MINUS, eliminateVar, in[1]); + // } + // // x = (p - ax - c) * -1/a + // eliminateVar = NodeManager::currentNM()->mkNode(kind::MULT, eliminateVar, mkRationalNode(- minConstant.inverse())); + // // Add the substitution if not recursive + Node rewritten = eliminateVar; + Assert(rewritten == Rewriter::rewrite(eliminateVar)); if (!rewritten.hasSubterm(minVar)) { Node elim = Rewriter::rewrite(eliminateVar); if (!minVar.getType().isInteger() || elim.getType().isInteger()) { @@ -584,21 +732,22 @@ void TheoryArith::setupPolynomial(const Polynomial& poly) { */ } -void TheoryArith::setupAtom(TNode atom, bool addToDatabase) { +void TheoryArith::setupAtom(TNode atom) { Assert(isRelationOperator(atom.getKind())); Assert(Comparison::isNormalAtom(atom)); Assert(!isSetup(atom)); + Assert(!d_constraintDatabase.hasLiteral(atom)); - Node left = atom[0]; - if(!isSetup(left)){ - Polynomial poly = Polynomial::parsePolynomial(left); - setupPolynomial(poly); - } + Comparison cmp = Comparison::parseNormalForm(atom); + Polynomial nvp = cmp.normalizedVariablePart(); + Assert(!nvp.isZero()); - if(addToDatabase){ - d_atomDatabase.addAtom(atom); + if(!isSetup(nvp.getNode())){ + setupPolynomial(nvp); } + d_constraintDatabase.addLiteral(atom); + markSetup(atom); } @@ -607,12 +756,17 @@ void TheoryArith::preRegisterTerm(TNode n) { if(isRelationOperator(n.getKind())){ if(!isSetup(n)){ - setupAtom(n, Options::current()->arithPropagation); + setupAtom(n); } - addToContext(n); + Constraint c = d_constraintDatabase.lookup(n); + Assert(c != NullConstraint); + + Debug("arith::preregister") << "setup constraint" << c << endl; + Assert(!c->canBePropagated()); + c->setPreregistered(); } - Debug("arith::preregister") << "end arith::preRegisterTerm(" << n <<")" << endl; + Debug("arith::preregister") << "end arith::preRegisterTerm("<< n <<")" << endl; } @@ -642,6 +796,8 @@ ArithVar TheoryArith::requestArithVar(TNode x, bool slack){ d_tableau.increaseSize(); + d_constraintDatabase.addVariable(varX); + Debug("arith::arithvar") << x << " |-> " << varX << endl; return varX; @@ -698,20 +854,22 @@ void TheoryArith::setupInitialValue(ArithVar x){ Debug("arith") << "setupVariable("<<x<<")"<<std::endl; } -ArithVar TheoryArith::determineLeftVariable(TNode assertion, Kind simpleKind){ - TNode left = getSide<true>(assertion, simpleKind); - - return d_arithvarNodeMap.asArithVar(left); +ArithVar TheoryArith::determineArithVar(const Polynomial& p) const{ + Assert(!p.containsConstant()); + Assert(p.getHead().constantIsPositive()); + TNode n = p.getNode(); + Debug("determineArithVar") << "determineArithVar(" << n << ")" << endl; + return d_arithvarNodeMap.asArithVar(n); } - -Node TheoryArith::disequalityConflict(TNode eq, TNode lb, TNode ub){ - NodeBuilder<3> conflict(kind::AND); - conflict << eq << lb << ub; - ++(d_statistics.d_statDisequalityConflicts); - return conflict; +ArithVar TheoryArith::determineArithVar(TNode assertion) const{ + Debug("determineArithVar") << "determineArithVar " << assertion << endl; + Comparison cmp = Comparison::parseNormalForm(assertion); + Polynomial variablePart = cmp.normalizedVariablePart(); + return determineArithVar(variablePart); } + bool TheoryArith::canSafelyAvoidEqualitySetup(TNode equality){ Assert(equality.getKind() == EQUAL); return d_arithvarNodeMap.hasArithVar(equality[0]); @@ -721,11 +879,11 @@ Comparison TheoryArith::mkIntegerEqualityFromAssignment(ArithVar v){ const DeltaRational& beta = d_partialModel.getAssignment(v); Assert(beta.isIntegral()); - Constant betaAsConstant = Constant::mkConstant(beta.floor()); + Polynomial betaAsPolynomial( Constant::mkConstant(beta.floor()) ); TNode var = d_arithvarNodeMap.asNode(v); Polynomial varAsPolynomial = Polynomial::parsePolynomial(var); - return Comparison::mkComparison(EQUAL, varAsPolynomial, betaAsConstant); + return Comparison::mkComparison(EQUAL, varAsPolynomial, betaAsPolynomial); } Node TheoryArith::dioCutting(){ @@ -755,12 +913,12 @@ Node TheoryArith::dioCutting(){ return Node::null(); }else{ Polynomial p = plane.getPolynomial(); - Constant c = plane.getConstant() * Constant::mkConstant(-1); + Polynomial c(plane.getConstant() * Constant::mkConstant(-1)); Integer gcd = p.gcd(); Assert(p.isIntegral()); Assert(c.isIntegral()); Assert(gcd > 1); - Assert(!gcd.divides(c.getValue().getNumerator())); + Assert(!gcd.divides(c.asConstant().getNumerator())); Comparison leq = Comparison::mkComparison(LEQ, p, c); Comparison geq = Comparison::mkComparison(GEQ, p, c); Node lemma = NodeManager::currentNM()->mkNode(OR, leq.getNode(), geq.getNode()); @@ -782,21 +940,17 @@ Node TheoryArith::callDioSolver(){ Assert(isInteger(v)); Assert(d_partialModel.boundsAreEqual(v)); - TNode lb = d_partialModel.getLowerConstraint(v); - TNode ub = d_partialModel.getUpperConstraint(v); + + Constraint lb = d_partialModel.getLowerBoundConstraint(v); + Constraint ub = d_partialModel.getUpperBoundConstraint(v); Node orig = Node::null(); - if(lb == ub){ - Assert(lb.getKind() == EQUAL); - orig = lb; - }else if(lb.getKind() == EQUAL){ - orig = lb; - }else if(ub.getKind() == EQUAL){ - orig = ub; - }else{ - NodeBuilder<> nb(AND); - nb << ub << lb; - orig = nb; + if(lb->isEquality()){ + orig = lb->explainForConflict(); + }else if(ub->isEquality()){ + orig = ub->explainForConflict(); + }else { + orig = ConstraintValue::explainConflict(ub, lb); } Assert(d_partialModel.assignmentIsConsistent(v)); @@ -819,71 +973,124 @@ Node TheoryArith::callDioSolver(){ } Node TheoryArith::assertionCases(TNode assertion){ - Kind simpleKind = simplifiedKind(assertion); + Constraint constraint = d_constraintDatabase.lookup(assertion); + + Kind simpleKind = Comparison::comparisonKind(assertion); Assert(simpleKind != UNDEFINED_KIND); + Assert(constraint != NullConstraint || + simpleKind == EQUAL || + simpleKind == DISTINCT ); if(simpleKind == EQUAL || simpleKind == DISTINCT){ Node eq = (simpleKind == DISTINCT) ? assertion[0] : assertion; if(!isSetup(eq)){ //The previous code was equivalent to: - setupAtom(eq, false); - //We can try: - //setupAtom(eq, true); - addToContext(eq); + setupAtom(eq); + constraint = d_constraintDatabase.lookup(assertion); + } + } + Assert(constraint != NullConstraint); + + if(constraint->negationHasProof()){ + Constraint negation = constraint->getNegation(); + if(negation->isSelfExplaining()){ + if(Debug.isOn("whytheoryenginewhy")){ + debugPrintFacts(); + } + cout << "Theory engine is sending me both a literal and its negation?" + << "BOOOOOOOOOOOOOOOOOOOOOO!!!!"<< endl; } + Debug("arith::eq") << constraint << endl; + Debug("arith::eq") << negation << endl; + + NodeBuilder<> nb(kind::AND); + nb << assertion; + negation->explainForConflict(nb); + Node conflict = nb; + Debug("arith::eq") << "conflict" << conflict << endl; + return conflict; } + Assert(!constraint->negationHasProof()); - ArithVar x_i = determineLeftVariable(assertion, simpleKind); - DeltaRational c_i = determineRightConstant(assertion, simpleKind); + if(constraint->assertedToTheTheory()){ + //Do nothing + return Node::null(); + } + Assert(!constraint->assertedToTheTheory()); + constraint->setAssertedToTheTheory(); - // bool tightened = false; + ArithVar x_i = constraint->getVariable(); + //DeltaRational c_i = determineRightConstant(assertion, simpleKind); - // //If the variable is an integer tighen the constraint. - // if(isInteger(x_i)){ - // if(simpleKind == LT){ - // tightened = true; - // c_i = DeltaRational(c_i.floor()); - // }else if(simpleKind == GT){ - // tightened = true; - // c_i = DeltaRational(c_i.ceiling()); - // } - // } + //Assert(constraint->getVariable() == determineLeftVariable(assertion, simpleKind)); + //Assert(constraint->getValue() == determineRightConstant(assertion, simpleKind)); + Assert(!constraint->hasLiteral() || constraint->getLiteral() == assertion); Debug("arith::assertions") << "arith assertion @" << getContext()->getLevel() <<"(" << assertion << " \\-> " - << x_i<<" "<< simpleKind <<" "<< c_i << ")" << std::endl; - - switch(simpleKind){ - case LEQ: - case LT: - return AssertUpper(x_i, c_i, assertion); - case GEQ: - case GT: - return AssertLower(x_i, c_i, assertion); - case EQUAL: - return AssertEquality(x_i, c_i, assertion); - case DISTINCT: - { - d_diseq.insert(assertion); - // Check if it conflicts with the the bounds - TNode eq = assertion[0]; - Assert(eq.getKind() == kind::EQUAL); - TNode lhs = eq[0]; - TNode rhs = eq[1]; - Assert(rhs.getKind() == CONST_RATIONAL); - ArithVar lhsVar = determineLeftVariable(eq, kind::EQUAL); - DeltaRational rhsValue = determineRightConstant(eq, kind::EQUAL); - if (d_partialModel.hasLowerBound(lhsVar) && - d_partialModel.hasUpperBound(lhsVar) && - d_partialModel.getLowerBound(lhsVar) == rhsValue && - d_partialModel.getUpperBound(lhsVar) == rhsValue) { - Node lb = d_partialModel.getLowerConstraint(lhsVar); - Node ub = d_partialModel.getUpperConstraint(lhsVar); - return disequalityConflict(assertion, lb, ub); + //<< determineLeftVariable(assertion, simpleKind) + <<" "<< simpleKind <<" " + //<< determineRightConstant(assertion, simpleKind) + << ")" << std::endl; + + + Debug("arith::constraint") << "arith constraint " << constraint << std::endl; + + if(!constraint->hasProof()){ + Debug("arith::constraint") << "marking as constraint as self explaining " << endl; + constraint->selfExplaining(); + }else{ + Debug("arith::constraint") << "already has proof: " << constraint->explainForConflict() << endl; + } + + Assert(!isInteger(x_i) || + simpleKind == EQUAL || + simpleKind == DISTINCT || + simpleKind == GEQ || + simpleKind == LT); + + switch(constraint->getType()){ + case UpperBound: + if(simpleKind == LT && isInteger(x_i)){ + Constraint floorConstraint = constraint->getFloor(); + if(!floorConstraint->isTrue()){ + if(floorConstraint->negationHasProof()){ + return ConstraintValue::explainConflict(constraint, floorConstraint->getNegation()); + }else{ + floorConstraint->impliedBy(constraint); + } } + //c_i = DeltaRational(c_i.floor()); + //return AssertUpper(x_i, c_i, assertion, floorConstraint); + return AssertUpper(floorConstraint); + }else{ + return AssertUpper(constraint); } - return Node::null(); + //return AssertUpper(x_i, c_i, assertion, constraint); + case LowerBound: + if(simpleKind == LT && isInteger(x_i)){ + Constraint ceilingConstraint = constraint->getCeiling(); + if(!ceilingConstraint->isTrue()){ + if(ceilingConstraint->negationHasProof()){ + + return ConstraintValue::explainConflict(constraint, ceilingConstraint->getNegation()); + } + ceilingConstraint->impliedBy(constraint); + } + //c_i = DeltaRational(c_i.ceiling()); + //return AssertLower(x_i, c_i, assertion, ceilingConstraint); + return AssertLower(ceilingConstraint); + }else{ + return AssertLower(constraint); + } + //return AssertLower(x_i, c_i, assertion, constraint); + case Equality: + return AssertEquality(constraint); + //return AssertEquality(x_i, c_i, assertion, constraint); + case Disequality: + return AssertDisequality(constraint); + //return AssertDisequality(x_i, c_i, assertion, constraint); default: Unreachable(); return Node::null(); @@ -930,29 +1137,45 @@ void TheoryArith::check(Effort effortLevel){ d_out->conflict(possibleConflict); return; } + if(d_differenceManager.inConflict()){ + Node c = d_differenceManager.conflict(); + d_partialModel.revertAssignmentChanges(); + Debug("arith::conflict") << "difference manager conflict " << c << endl; + clearUpdates(); + d_out->conflict(c); + return; + } } + if(Debug.isOn("arith::print_assertions")) { debugPrintAssertions(); } bool emmittedConflictOrSplit = false; - Node possibleConflict = d_simplex.findModel(); - if(possibleConflict != Node::null()){ + Assert(d_conflicts.empty()); + bool foundConflict = d_simplex.findModel(); + if(foundConflict){ d_partialModel.revertAssignmentChanges(); clearUpdates(); - Debug("arith::conflict") << "conflict " << possibleConflict << endl; - d_out->conflict(possibleConflict); + Assert(!d_conflicts.empty()); + for(size_t i = 0, i_end = d_conflicts.size(); i < i_end; ++i){ + Node conflict = d_conflicts[i]; + Debug("arith::conflict") << "d_conflicts[" << i << "] " << conflict << endl; + d_out->conflict(conflict); + } emmittedConflictOrSplit = true; }else{ d_partialModel.commitAssignmentChanges(); } + if(!emmittedConflictOrSplit && fullEffort(effortLevel)){ emmittedConflictOrSplit = splitDisequalities(); } + Node possibleConflict = Node::null(); if(!emmittedConflictOrSplit && fullEffort(effortLevel) && !hasIntegerModel()){ if(!emmittedConflictOrSplit && Options::current()->dioSolver){ @@ -1034,29 +1257,43 @@ Node TheoryArith::roundRobinBranch(){ bool TheoryArith::splitDisequalities(){ bool splitSomething = false; - context::CDHashSet<Node, NodeHashFunction>::iterator it = d_diseq.begin(); - context::CDHashSet<Node, NodeHashFunction>::iterator it_end = d_diseq.end(); - for(; it != it_end; ++ it) { - TNode eq = (*it)[0]; - Assert(eq.getKind() == kind::EQUAL); - TNode lhs = eq[0]; - TNode rhs = eq[1]; - Assert(rhs.getKind() == CONST_RATIONAL); - ArithVar lhsVar = determineLeftVariable(eq, kind::EQUAL); - DeltaRational lhsValue = d_partialModel.getAssignment(lhsVar); - DeltaRational rhsValue = determineRightConstant(eq, kind::EQUAL); - if (lhsValue == rhsValue) { - Debug("arith::lemma") << "Splitting on " << eq << endl; - Debug("arith::lemma") << "LHS value = " << lhsValue << endl; - Debug("arith::lemma") << "RHS value = " << rhsValue << endl; - Node ltNode = NodeBuilder<2>(kind::LT) << lhs << rhs; - Node gtNode = NodeBuilder<2>(kind::GT) << lhs << rhs; - Node lemma = NodeBuilder<3>(OR) << eq << ltNode << gtNode; - ++(d_statistics.d_statDisequalitySplits); - d_out->lemma(lemma); - splitSomething = true; + vector<Constraint> save; + + while(!d_diseqQueue.empty()){ + Constraint front = d_diseqQueue.front(); + d_diseqQueue.pop(); + + if(front->isSplit()){ + Debug("eq") << "split already" << endl; + }else{ + Debug("eq") << "not split already" << endl; + + ArithVar lhsVar = front->getVariable(); + + const DeltaRational& lhsValue = d_partialModel.getAssignment(lhsVar); + const DeltaRational& rhsValue = front->getValue(); + if(lhsValue == rhsValue){ + Debug("arith::lemma") << "Splitting on " << front << endl; + Debug("arith::lemma") << "LHS value = " << lhsValue << endl; + Debug("arith::lemma") << "RHS value = " << rhsValue << endl; + Node lemma = front->split(); + ++(d_statistics.d_statDisequalitySplits); + d_out->lemma(lemma); + splitSomething = true; + }else if(d_partialModel.strictlyLessThanLowerBound(lhsVar, rhsValue)){ + Debug("eq") << "can drop as less than lb" << front << endl; + }else if(d_partialModel.strictlyGreaterThanUpperBound(lhsVar, rhsValue)){ + Debug("eq") << "can drop as greater than ub" << front << endl; + }else{ + Debug("eq") << "save" << front << endl; + save.push_back(front); + } } } + vector<Constraint>::const_iterator i=save.begin(), i_end = save.end(); + for(; i != i_end; ++i){ + d_diseqQueue.push(*i); + } return splitSomething; } @@ -1068,17 +1305,17 @@ void TheoryArith::debugPrintAssertions() { Debug("arith::print_assertions") << "Assertions:" << endl; for (ArithVar i = 0; i < d_variables.size(); ++ i) { if (d_partialModel.hasLowerBound(i)) { - Node lConstr = d_partialModel.getLowerConstraint(i); + Constraint lConstr = d_partialModel.getLowerBoundConstraint(i); Debug("arith::print_assertions") << lConstr << endl; } if (d_partialModel.hasUpperBound(i)) { - Node uConstr = d_partialModel.getUpperConstraint(i); + Constraint uConstr = d_partialModel.getUpperBoundConstraint(i); Debug("arith::print_assertions") << uConstr << endl; } } - context::CDHashSet<Node, NodeHashFunction>::iterator it = d_diseq.begin(); - context::CDHashSet<Node, NodeHashFunction>::iterator it_end = d_diseq.end(); + context::CDQueue<Constraint>::const_iterator it = d_diseqQueue.begin(); + context::CDQueue<Constraint>::const_iterator it_end = d_diseqQueue.end(); for(; it != it_end; ++ it) { Debug("arith::print_assertions") << *it << endl; } @@ -1097,88 +1334,74 @@ void TheoryArith::debugPrintModel(){ } Node TheoryArith::explain(TNode n) { - Debug("arith::explain") << "explain @" << getContext()->getLevel() << ": " << n << endl; - Assert(d_propManager.isPropagated(n)); - return d_propManager.explain(n); -} + Debug("arith::explain") << "explain @" << getContext()->getLevel() << ": " << n << endl; -void flattenAnd(Node n, std::vector<TNode>& out){ - Assert(n.getKind() == kind::AND); - for(Node::iterator i=n.begin(), i_end=n.end(); i != i_end; ++i){ - Node curr = *i; - if(curr.getKind() == kind::AND){ - flattenAnd(curr, out); - }else{ - out.push_back(curr); - } + Constraint c = d_constraintDatabase.lookup(n); + if(c != NullConstraint){ + Assert(!c->isSelfExplaining()); + Node exp = c->explainForPropagation(); + Debug("arith::explain") << "constraint explanation" << n << ":" << exp << endl; + return exp; + }else{ + Assert(d_differenceManager.canExplain(n)); + Debug("arith::explain") << "dm explanation" << n << endl; + return d_differenceManager.explain(n); } } -Node flattenAnd(Node n){ - std::vector<TNode> out; - flattenAnd(n, out); - return NodeManager::currentNM()->mkNode(kind::AND, out); -} void TheoryArith::propagate(Effort e) { - bool propagated = false; if(Options::current()->arithPropagation && hasAnyUpdates()){ propagateCandidates(); }else{ clearUpdates(); } - while(d_propManager.hasMorePropagations()){ - const PropManager::PropUnit next = d_propManager.getNextPropagation(); - bool flag = next.flag; - TNode toProp = next.consequent; + while(d_constraintDatabase.hasMorePropagations()){ + Constraint c = d_constraintDatabase.nextPropagation(); - TNode atom = (toProp.getKind() == kind::NOT) ? toProp[0] : toProp; + if(c->negationHasProof()){ + Node conflict = ConstraintValue::explainConflict(c, c->getNegation()); + cout << "tears " << conflict << endl; + Debug("arith::prop") << "propagate conflict" << conflict << endl; + d_out->conflict(conflict); + return; + }else if(!c->assertedToTheTheory()){ - Debug("arith::propagate") << "propagate @" << getContext()->getLevel() <<" flag: "<< flag << " " << toProp << endl; + Node literal = c->getLiteral(); + Debug("arith::prop") << "propagating @" << getContext()->getLevel() << " " << literal << endl; - if(flag) { - //Currently if the flag is set this came from an equality detected by the - //equality engine in the the difference manager. - if(toProp.getKind() == kind::EQUAL){ - Node normalized = Rewriter::rewrite(toProp); - Node notNormalized = normalized.notNode(); + d_out->propagate(literal); + }else{ + Node literal = c->getLiteral(); + Debug("arith::prop") << "already asserted to the theory " << literal << endl; + } + } - if(d_diseq.find(notNormalized) == d_diseq.end()){ - d_out->propagate(toProp); - propagated = true; - }else{ - Node exp = d_differenceManager.explain(toProp); - Node lp = flattenAnd(exp.andNode(notNormalized)); - Debug("arith::propagate") << "propagate conflict" << lp << endl; - d_out->conflict(lp); + while(d_differenceManager.hasMorePropagations()){ + TNode toProp = d_differenceManager.getNextPropagation(); - propagated = true; - break; - } - }else{ - d_out->propagate(toProp); - propagated = true; - } - }else if(inContextAtom(atom)){ - Node satValue = d_valuation.getSatValue(toProp); - AlwaysAssert(satValue.isNull()); - propagated = true; + //Currently if the flag is set this came from an equality detected by the + //equality engine in the the difference manager. + Node normalized = Rewriter::rewrite(toProp); + + Constraint constraint = d_constraintDatabase.lookup(normalized); + if(constraint == NullConstraint){ + Debug("arith::prop") << "propagating on non-constraint? " << toProp << endl; d_out->propagate(toProp); + }else if(constraint->negationHasProof()){ + Node exp = d_differenceManager.explain(toProp); + Node notNormalized = normalized.getKind() == NOT ? + normalized[0] : normalized.notNode(); + Node lp = flattenAnd(exp.andNode(notNormalized)); + Debug("arith::prop") << "propagate conflict" << lp << endl; + d_out->conflict(lp); + return; }else{ - //Not clear if this is a good time to do this or not... - Debug("arith::propagate") << "Atom is not in context" << toProp << endl; -#warning "enable remove atom in database" - //d_atomDatabase.removeAtom(atom); - } - } + Debug("arith::prop") << "propagating still?" << toProp << endl; - if(!propagated){ - //Opportunistically export previous conflicts - while(d_simplex.hasMoreLemmas()){ - Node lemma = d_simplex.popLemma(); - d_out->lemma(lemma); + d_out->propagate(toProp); } } } @@ -1401,8 +1624,18 @@ void TheoryArith::presolve(){ callCount = callCount + 1; } + if(Options::current()->arithPropagation ){ + vector<Node> lemmas; + d_constraintDatabase.outputAllUnateLemmas(lemmas); + vector<Node>::const_iterator i = lemmas.begin(), i_end = lemmas.end(); + for(; i != i_end; ++i){ + Node lem = *i; + Debug("arith::oldprop") << " lemma lemma duck " <<lem << endl; + d_out->lemma(lem); + } + } + d_learner.clear(); - check(EFFORT_FULL); } EqualityStatus TheoryArith::getEqualityStatus(TNode a, TNode b) { @@ -1423,27 +1656,71 @@ bool TheoryArith::propagateCandidateBound(ArithVar basic, bool upperBound){ if((upperBound && d_partialModel.strictlyLessThanUpperBound(basic, bound)) || (!upperBound && d_partialModel.strictlyGreaterThanLowerBound(basic, bound))){ - Node bestImplied = upperBound ? - d_propManager.getBestImpliedUpperBound(basic, bound): - d_propManager.getBestImpliedLowerBound(basic, bound); - if(!bestImplied.isNull()){ - bool asserted = d_propManager.isAsserted(bestImplied); - bool propagated = d_propManager.isPropagated(bestImplied); - if( !asserted && !propagated){ +#warning "Policy point" + //We are only going to recreate the functionality for now. + //In the future this can be improved to generate a temporary constraint + //if none exists. + //Experiment with doing this everytime or only when the new constraint + //implies an unknown fact. + + ConstraintType t = upperBound ? UpperBound : LowerBound; + Constraint bestImplied = d_constraintDatabase.getBestImpliedBound(basic, t, bound); - NodeBuilder<> nb(kind::AND); + // Node bestImplied = upperBound ? + // d_apm.getBestImpliedUpperBound(basic, bound): + // d_apm.getBestImpliedLowerBound(basic, bound); + + if(bestImplied != NullConstraint){ + //This should be stronger + Assert(!upperBound || bound <= bestImplied->getValue()); + Assert(!upperBound || d_partialModel.lessThanUpperBound(basic, bestImplied->getValue())); + + Assert( upperBound || bound >= bestImplied->getValue()); + Assert( upperBound || d_partialModel.greaterThanLowerBound(basic, bestImplied->getValue())); + //slightly changed + + // Constraint c = d_constraintDatabase.lookup(bestImplied); + // Assert(c != NullConstraint); + + bool assertedToTheTheory = bestImplied->assertedToTheTheory(); + bool canBePropagated = bestImplied->canBePropagated(); + bool hasProof = bestImplied->hasProof(); + + Debug("arith::prop") << "arith::prop" << basic + //<< " " << assertedValuation + << " " << assertedToTheTheory + << " " << canBePropagated + << " " << hasProof + << endl; + + if(!assertedToTheTheory && canBePropagated && !hasProof ){ if(upperBound){ - d_linEq.explainNonbasicsUpperBound(basic, nb); + Assert(bestImplied != d_partialModel.getUpperBoundConstraint(basic)); + d_linEq.propagateNonbasicsUpperBound(basic, bestImplied); }else{ - d_linEq.explainNonbasicsLowerBound(basic, nb); + Assert(bestImplied != d_partialModel.getLowerBoundConstraint(basic)); + d_linEq.propagateNonbasicsLowerBound(basic, bestImplied); } - Node explanation = nb; - d_propManager.propagate(bestImplied, explanation, false); return true; - }else{ - Debug("arith::prop") << basic << " " << asserted << " " << propagated << endl; } + + // bool asserted = valuationIsAsserted(bestImplied); + // bool propagated = d_theRealPropManager.isPropagated(bestImplied); + // if( !asserted && !propagated){ + + // NodeBuilder<> nb(kind::AND); + // if(upperBound){ + // d_linEq.explainNonbasicsUpperBound(basic, nb); + // }else{ + // d_linEq.explainNonbasicsLowerBound(basic, nb); + // } + // Node explanation = nb; + // d_theRealPropManager.propagate(bestImplied, explanation, false); + // return true; + // }else{ + // Debug("arith::prop") << basic << " " << asserted << " " << propagated << endl; + // } } } return false; diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h index 4f111d350..4a5c398bd 100644 --- a/src/theory/arith/theory_arith.h +++ b/src/theory/arith/theory_arith.h @@ -34,14 +34,14 @@ #include "theory/arith/arith_rewriter.h" #include "theory/arith/partial_model.h" #include "theory/arith/linear_equality.h" -#include "theory/arith/atom_database.h" #include "theory/arith/simplex.h" #include "theory/arith/arith_static_learner.h" -#include "theory/arith/arith_prop_manager.h" #include "theory/arith/arithvar_node_map.h" #include "theory/arith/dio_solver.h" #include "theory/arith/difference_manager.h" +#include "theory/arith/constraint.h" + #include "util/stats.h" #include <vector> @@ -66,24 +66,6 @@ private: */ bool d_hasDoneWorkSinceCut; - /** - * The set of atoms that are currently in the context. - * This is exactly the union of preregistered atoms and - * equalities from sharing. - * This is used to reconstruct the rest of arithmetic. - */ - CDNodeSet d_atomsInContext; - bool inContextAtom(TNode atom){ - Assert(isRelationOperator(atom.getKind())); - Assert(Comparison::isNormalAtom(atom)); - return d_atomsInContext.contains(atom); - } - void addToContext(TNode atom){ - Assert(isRelationOperator(atom.getKind())); - Assert(Comparison::isNormalAtom(atom)); - d_atomsInContext.insert(atom); - } - /** Static learner. */ ArithStaticLearner d_learner; @@ -111,8 +93,20 @@ private: void setupVariable(const Variable& x); void setupVariableList(const VarList& vl); void setupPolynomial(const Polynomial& poly); - void setupAtom(TNode atom, bool addToDatabase); + void setupAtom(TNode atom); + class SetupLiteralCallBack : public TNodeCallBack { + private: + TheoryArith* d_arith; + public: + SetupLiteralCallBack(TheoryArith* ta) : d_arith(ta){} + void operator()(TNode lit){ + TNode atom = (lit.getKind() == kind::NOT) ? lit[0] : lit; + if(!d_arith->isSetup(atom)){ + d_arith->setupAtom(atom); + } + } + } d_setupLiteralCallback; /** * (For the moment) the type hierarchy goes as: @@ -172,7 +166,9 @@ private: /** * List of all of the inequalities asserted in the current context. */ - context::CDHashSet<Node, NodeHashFunction> d_diseq; + //context::CDHashSet<Node, NodeHashFunction> d_diseq; + context::CDQueue<Constraint> d_diseqQueue; + /** * Manages information about the assignment and upper and lower bounds on @@ -222,6 +218,23 @@ private: uint32_t d_tableauResetPeriod; static const uint32_t s_TABLEAU_RESET_INCREMENT = 5; + + /** This is only used by simplex at the moment. */ + context::CDList<Node> d_conflicts; + class PushCallBack : public NodeCallBack { + private: + context::CDList<Node>& d_list; + public: + PushCallBack(context::CDList<Node>& l) + : d_list(l) + {} + void operator()(Node n){ + d_list.push_back(n); + } + }; + PushCallBack d_conflictCallBack; + + /** * A copy of the tableau immediately after removing variables * without bounds in presolve(). @@ -232,10 +245,7 @@ private: * The atom database keeps track of the atoms that have been preregistered. * Used to add unate propagations. */ - ArithAtomDatabase d_atomDatabase; - - /** This manager keeps track of information needed to propagate. */ - ArithPropManager d_propManager; + //ArithAtomDatabase d_atomDatabase; /** This keeps track of difference equalities. Mostly for sharing. */ DifferenceManager d_differenceManager; @@ -243,6 +253,10 @@ private: /** This implements the Simplex decision procedure. */ SimplexDecisionProcedure d_simplex; + + /** The constraint database associated with the theory. */ + ConstraintDatabase d_constraintDatabase; + /** Internal model value for the atom */ bool getDeltaAtomValue(TNode n); @@ -291,7 +305,7 @@ private: d_simplex(s) {} - void callback(ArithVar x){ + void operator()(ArithVar x){ d_simplex.updateBasic(x); } }; @@ -305,10 +319,10 @@ private: void propagateArithVar(bool upperbound, ArithVar var ); /** - * Using the simpleKind return the ArithVar associated with the - * left hand side of assertion. + * Using the simpleKind return the ArithVar associated with the assertion. */ - ArithVar determineLeftVariable(TNode assertion, Kind simpleKind); + ArithVar determineArithVar(const Polynomial& p) const; + ArithVar determineArithVar(TNode assertion) const; /** * Splits the disequalities in d_diseq that are violated using lemmas on demand. @@ -317,6 +331,8 @@ private: */ bool splitDisequalities(); + /** A Difference variable is known to be 0.*/ + void zeroDifferenceDetected(ArithVar x); /** @@ -364,9 +380,10 @@ private: * a node describing this conflict is returned. * If this new bound is not in conflict, Node::null() is returned. */ - Node AssertLower(ArithVar x, DeltaRational& c, TNode orig); - Node AssertUpper(ArithVar x, DeltaRational& c, TNode orig); - Node AssertEquality(ArithVar x, DeltaRational& c, TNode orig); + Node AssertLower(Constraint constraint); + Node AssertUpper(Constraint constraint); + Node AssertEquality(Constraint constraint); + Node AssertDisequality(Constraint constraint); /** Tracks the bounds that were updated in the current round. */ PermissiveBackArithVarSet d_updatedBounds; @@ -401,11 +418,6 @@ private: Node assertionCases(TNode assertion); /** - * This is used for reporting conflicts caused by disequalities during assertionCases. - */ - Node disequalityConflict(TNode eq, TNode lb, TNode ub); - - /** * Returns the basic variable with the shorted row containg a non-basic variable. * If no such row exists, return ARITHVAR_SENTINEL. */ diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp index afd311bf2..cde65aa0f 100644 --- a/src/theory/theory.cpp +++ b/src/theory/theory.cpp @@ -83,5 +83,10 @@ void Theory::printFacts(std::ostream& os) const { } } +void Theory::debugPrintFacts() const{ + cout << "Theory::debugPrintFacts()" << endl; + printFacts(cout); +} + }/* CVC4::theory namespace */ }/* CVC4 namespace */ diff --git a/src/theory/theory.h b/src/theory/theory.h index 28fdc8cbe..2b91da3b2 100644 --- a/src/theory/theory.h +++ b/src/theory/theory.h @@ -263,6 +263,7 @@ protected: static TheoryId s_uninterpretedSortOwner; void printFacts(std::ostream& os) const; + void debugPrintFacts() const; public: diff --git a/src/util/integer_cln_imp.h b/src/util/integer_cln_imp.h index 9d67e8fba..d3e5c07ca 100644 --- a/src/util/integer_cln_imp.h +++ b/src/util/integer_cln_imp.h @@ -366,6 +366,18 @@ public: return cln::cl_I_to_int(sgn); } + bool isZero() const { + return cln::zerop(d_value); + } + + bool isOne() const { + return d_value == 1; + } + + bool isNegativeOne() const { + return d_value == -1; + } + //friend std::ostream& operator<<(std::ostream& os, const Integer& n); long getLong() const { diff --git a/src/util/integer_gmp_imp.h b/src/util/integer_gmp_imp.h index ceb585852..74b4adad0 100644 --- a/src/util/integer_gmp_imp.h +++ b/src/util/integer_gmp_imp.h @@ -276,6 +276,18 @@ public: return mpz_sgn(d_value.get_mpz_t()); } + bool isZero() const { + return sgn() == 0; + } + + bool isOne() const { + return mpz_cmp_si(d_value.get_mpz_t(), 1) == 0; + } + + bool isNegativeOne() const { + return mpz_cmp_si(d_value.get_mpz_t(), -1) == 0; + } + /** * Raise this Integer to the power <code>exp</code>. * diff --git a/src/util/options.cpp b/src/util/options.cpp index b6956a31b..b6a306ee0 100644 --- a/src/util/options.cpp +++ b/src/util/options.cpp @@ -110,6 +110,7 @@ Options::Options() : ufSymmetryBreaker(false), ufSymmetryBreakerSetByUser(false), dioSolver(true), + arithRewriteEq(true), lemmaOutputChannel(NULL), lemmaInputChannel(NULL), threads(2),// default should be 1 probably, but say 2 for now @@ -183,6 +184,7 @@ Additional CVC4 options:\n\ --enable-symmetry-breaker turns on UF symmetry breaker (Deharbe et al., CADE 2011) [on by default only for QF_UF]\n\ --disable-symmetry-breaker turns off UF symmetry breaker\n\ --disable-dio-solver turns off Linear Diophantine Equation solver (Griggio, JSAT 2012)\n\ + --disable-arith-rewrite-equalities turns off the preprocessing rewrite turning equalities into a conjunction of inequalities.\n \ --threads=N sets the number of solver threads\n\ --threadN=string configures thread N (0..#threads-1)\n\ --filter-lemma-length=N don't share lemmas strictly longer than N\n\ @@ -356,6 +358,7 @@ enum OptionValue { ARITHMETIC_PIVOT_THRESHOLD, ARITHMETIC_PROP_MAX_LENGTH, ARITHMETIC_DIO_SOLVER, + ARITHMETIC_REWRITE_EQUALITIES, ENABLE_SYMMETRY_BREAKER, DISABLE_SYMMETRY_BREAKER, PARALLEL_THREADS, @@ -445,6 +448,7 @@ static struct option cmdlineOptions[] = { { "print-winner", no_argument , NULL, PRINT_WINNER }, { "disable-arithmetic-propagation", no_argument, NULL, ARITHMETIC_PROPAGATION }, { "disable-dio-solver", no_argument, NULL, ARITHMETIC_DIO_SOLVER }, + { "disable-arith-rewrite-equalities", no_argument, NULL, ARITHMETIC_REWRITE_EQUALITIES }, { "enable-symmetry-breaker", no_argument, NULL, ENABLE_SYMMETRY_BREAKER }, { "disable-symmetry-breaker", no_argument, NULL, DISABLE_SYMMETRY_BREAKER }, { "threads", required_argument, NULL, PARALLEL_THREADS }, @@ -796,6 +800,10 @@ throw(OptionException) { dioSolver = false; break; + case ARITHMETIC_REWRITE_EQUALITIES: + arithRewriteEq = false; + break; + case ENABLE_SYMMETRY_BREAKER: ufSymmetryBreaker = true; ufSymmetryBreakerSetByUser = true; diff --git a/src/util/options.h b/src/util/options.h index 4bf8b5b75..c7fbcd896 100644 --- a/src/util/options.h +++ b/src/util/options.h @@ -156,7 +156,7 @@ struct CVC4_PUBLIC Options { /** Whether we produce proofs. */ bool proof; - + /** Whether we support SmtEngine::getAssignment() for this run. */ bool produceAssignments; @@ -195,7 +195,7 @@ struct CVC4_PUBLIC Options { /** Variable activity decay factor for Minisat */ double satVarDecay; - + /** Clause activity decay factor for Minisat */ double satClauseDecay; @@ -238,6 +238,12 @@ struct CVC4_PUBLIC Options { */ bool dioSolver; + /** + * Whether to split (= x y) into (and (<= x y) (>= x y)) in + * arithmetic preprocessing. + */ + bool arithRewriteEq; + /** The output channel to receive notfication events for new lemmas */ LemmaOutputChannel* lemmaOutputChannel; LemmaInputChannel* lemmaInputChannel; @@ -251,7 +257,7 @@ struct CVC4_PUBLIC Options { /** Thread ID, for internal use in case of multi-threaded run */ int thread_id; - /** + /** * In multi-threaded setting print output of each thread at the * end of run, separated by a divider ("----"). **/ diff --git a/src/util/rational_cln_imp.h b/src/util/rational_cln_imp.h index 69eede0d6..c2da0e7ed 100644 --- a/src/util/rational_cln_imp.h +++ b/src/util/rational_cln_imp.h @@ -196,6 +196,14 @@ public: return cln::zerop(d_value); } + bool isOne() const { + return d_value == 1; + } + + bool isNegativeOne() const { + return d_value == -1; + } + Rational abs() const { if(sgn() < 0){ return -(*this); diff --git a/src/util/rational_gmp_imp.h b/src/util/rational_gmp_imp.h index 751c8f137..ef0720263 100644 --- a/src/util/rational_gmp_imp.h +++ b/src/util/rational_gmp_imp.h @@ -173,6 +173,14 @@ public: return sgn() == 0; } + bool isOne() const { + return mpq_cmp_si(d_value.get_mpq_t(), 1, 1) == 0; + } + + bool isNegativeOne() const { + return mpq_cmp_si(d_value.get_mpq_t(), -1, 1) == 0; + } + Rational abs() const { if(sgn() < 0){ return -(*this); |