pax_global_header00006660000000000000000000000064132001135230014500gustar00rootroot0000000000000052 comment=e2187b697f738f236828f7f780b5481c9a9284e6 clingo-5.2.2/000077500000000000000000000000001320011352300127615ustar00rootroot00000000000000clingo-5.2.2/.gitignore000066400000000000000000000003461320011352300147540ustar00rootroot00000000000000*.swp build *.pyc doc/api/html doc/api/latex *.opendb Debug Release ReleaseScript .vs *.db *.vcxproj.user x64 libgringo/generated .nfs* examples/clingo/pydoc/clingo.ast.html examples/clingo/pydoc/clingo.html cmake/FindBISON.cmake clingo-5.2.2/CHANGES.md000066400000000000000000000204001320011352300143470ustar00rootroot00000000000000# Changes ## clingo 5.2.2 * update to clasp version 3.3.3 * use GNUInstallDirs in cmake files to simplify packaging * fix --pre option * fix swapped clingo\_assignment\_size and clingo\_assignment\_max\_size * fix docstrings * fix incremental mode * fix sup and inf in python/lua bindings * fix reified format term tuples * fix wrong use of python API (causing trouble with python 3.6) * fix compilation problems on 32bit linux (missing libatomic) ## clingo 5.2.1 * update to clasp version 3.3.2 * fix handling of istop in incmode programs * fix handling of undefined ** operations * fix preprocessing of disjunctions with undefined operations (regression in clingo-5) * fix segfault during preprocessing (regression in clingo-5) ## clingo 5.2.0 * switch to MIT license * improve compatibility with abstract gringo * switch build system from scons to cmake * improve windows compatibility * make tests and examples python 3 compatible * bison and re2c are no longer required to build source releases * update to clasp 3.3.0 * the CLINGOPATH environment variable can be set to control from where to include files in logic programs * propagators can add variables while solving now * refactor interfaces (breaking backward compatibility) * there is just one solve function now * in the C API do not pass structs by value to functions because FFIs of some languages do not support this * fix cleanup function * numerous other bugfixes not listed here ## clingo 5.1.1 * fix thread id to start with one in propagator.undo in lua * fix version macro in clingo.h * fix added missing methods to get thread id to model in lua/python * fix child\_key property in python ast ## clingo 5.1.0 * update to clasp 3.2.1 * add interface to add variables during propagation * add interface to inspect ground rules (C/C++ only) * add experimental interface to access clasp facade (C/C++ only) * fixed smodels output (--output=smodels) ## clingo 5.0.0 * cleanup of python and lua API (breaks backwards compatibility) * added new aspif output format replacing the old smodels format * added input language support for clasp features * #edge directives to add acyclicity constraints * #project directives for enumeration of projected models * #heuristic directives to steer clasp's search * added theory atoms to write aggregate like constructs * added stable C API documented with doxygen * added experimental C++ API based on C API * added theory propagator interface to clingo APIs * added support for compilation with Visual Studio 2015 * improved data structures to reduce memory consumption on typical input * updated to clasp version 3.2.0 + patches ## gringo/clingo 4.5.4 * fixed bug when creating multiple Control objects (affects lua only) * fixed bug when trying to configure more solvers than in portfolio (affects python only) * fixed #disjoint constraints * improved build scripts * added option to keep facts in normal rules ## gringo/clingo 4.5.3 * fixed regression w.r.t gringo 4.4 in translation of conditional literals * fixed projection in incremental programs * fixed bug with (double) negative literals in minimize constraints ## gringo/clingo 4.5.2 * fixed memory leak in python API when enumerating models * updated to clasp version 3.1.3 ## gringo/clingo 4.5.1 * ground term parser returns None/nil for undefined terms now * added warning if a global variable occurs in a tuple of an aggregate element * added auto detection of libraries * changed option --update-domains into API function Control:cleanup\_domains * fixed domain cleanup when used with minimize constraints * fixed grounding of recursive disjunctions (regression in 4.5.0) * fixed Control.stats in lua bindings * fixed a bug in clingo that would print 0-ary classically negated atoms wrongly ## gringo/clingo 4.5.0 * fixed grounding of recursive aggregates * fixed usage of lua\_next * fixed bug when applying constant definitions * updated underlying clasp to version 3.1.1 * added support for negation in front of relation literals * added option --update-domains to cleanup gringo's domains using clasp's top-level assignment when solving incrementally * added domain inspection to scripting interface * added term parser to scripting interface * added support for python 3 (experimental) * added support for one elementary tuples * added support for unary - operator in front of functions and symbols * added support for recursive nonmonotone aggregate via translation * added program reify to reify logic programs * added option to rewrite minimize constaints for use with reify * changed inbuilt iclingo mode (breaks backwards compatibility) * changed handling of pools, intervals, and undefined operations according to AG (breaks backwards compatibility) * changed handling of ==, it is treated like = now * changed SolveFuture.interrupt to SolveFuture.cancel (breaks backwards compatibility) ## gringo/clingo 4.4.0 * updated underlying clasp to version 3.1.0 * this version brings numerous fixes regarding incremental solving * scripting API changes * ground takes a list of programs to ground now and immediately starts grounding (breaks backwards compatibility) * asolve has been renamed to solveAsync (breaks backwards compatibility) * the solver configuration is better integrated now (breaks backwards compatibility) * solver statistics are a property now (breaks backwards compatibility) * added a method to add clauses during solving * added load method to load files * added solveIter method to iterate over methods without using a callback * added optional assumptions to solve/solveAsync/solveIter method * enableEnumAssumption became a property * added library that can be imported in python * rules with fact heads where not simplified in all cases * fixed grounding of recursive aggregates * fixed translation of aggregates with multiple guards ## gringo/clingo 4.3.0 * fixed bug with incremental parameters in minimize constraints * fixed handling of empty tuples * fixed translation of conditional literals * fixed translation of factual body aggregates * fixed bug not properly recognizing aggregates as non-monotone * fixed bug not properly grounding recursive head aggregates * fixed bug with recursive negated aggregates * fixed bug with head aggregates with multiple elements * improved handling of conditional literals * added method to get optimization values of model in scripting language * clingo uses clasp 3.0 now ## gringo/clingo 4.2.1 * fixed bug in simplification of aggregates * fixed bug with raw strings in macros * fixed compilation issues with older glibc versions * fixed output for enumeration of cautious consequences * fixed bugs in clasp library * fixed race in parallel model enumeration * fixed incremental optimization * fixed cleanup up of learnt constraints during incremental solving * workaround for libstdc++'s bad choice for hash on 32bit arches ## gringo/clingo 4.2 * added clingo * supports very flexible scripting support * can cover iclingo and oclingo functionality now * added stack traces to lua error messages * added support for incremental optimization * improved python error messages * renamed gringo.Function to gringo.Fun * removed luabind dependency * removed boost-python dependency * consistently use not instead of #not as keyword for negation * fixed translation of conditions in head aggregates * fixed replacement of constants * fixed grounding of recursive head aggregates * fixed translation of head aggregates * fixed show statements for CSP variables (condition was ignored) * fixed plain text output of body aggregates * added a ton of new bugs ## gringo 4.1 * added scripting languages python and lua * added -c option to define constants * added constraints over integer variables * linear constraints * disjoint constraints * show statements for constraint variables * (experimental and subject to change) * improved translation of disjunctions * fixed include directives * fixed preprocessing of definitions * fixed lparse translation of optimization constructs clingo-5.2.2/CMakeLists.txt000066400000000000000000000153011320011352300155210ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.1) file(READ "libclingo/clingo.h" clingoh) string(REGEX MATCH "#define CLINGO_VERSION \"([^\"]*)\"" clingov ${clingoh}) project(CLINGO VERSION "${CMAKE_MATCH_1}" LANGUAGES C CXX) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "No build type selected - using 'Release'") set(CMAKE_BUILD_TYPE "Release") endif() include(GNUInstallDirs) include(CMakeDependentOption) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(clingo_functions) # Enable folders in IDEs like Visual Studio set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) option(CLINGO_BUILD_WEB "enable web target" OFF) option(CLINGO_BUILD_STATIC "do not build shared libraries" OFF) option(CLINGO_BUILD_WITH_PYTHON "enable python support" ON) option(CLINGO_BUILD_WITH_LUA "enable lua support" ON) option(CLINGO_BUILD_TESTS "build tests" OFF) option(CLINGO_BUILD_EXAMPLES "build examples" OFF) option(CLINGO_BUILD_APPS "build applications" ON) option(CLINGO_MANAGE_RPATH "set rpath if not installed into system directory" ON) CMAKE_DEPENDENT_OPTION(CLINGO_REQUIRE_PYTHON "fail if python support not found" OFF "CLINGO_BUILD_WITH_PYTHON" OFF) CMAKE_DEPENDENT_OPTION(CLINGO_REQUIRE_LUA "fail if lua support not found" OFF "CLINGO_BUILD_WITH_LUA" OFF) CMAKE_DEPENDENT_OPTION(CLINGO_BUILD_SHARED "build clingo library shared" ON "NOT CLINGO_BUILD_STATIC" OFF) CMAKE_DEPENDENT_OPTION(CLINGO_BUILD_PY_SHARED "build pyclingo library shared" OFF "NOT CLINGO_BUILD_STATIC" OFF) CMAKE_DEPENDENT_OPTION(CLINGO_BUILD_LUA_SHARED "build luaclingo library shared" OFF "NOT CLINGO_BUILD_STATIC" OFF) option(PYCLINGO_USER_INSTALL "install the python module in the user's site directory" ON) CMAKE_DEPENDENT_OPTION(PYCLINGO_USE_INSTALL_PREFIX "install the python module under the install prefix" OFF "NOT PYCLINGO_USER_INSTALL" OFF) set(CLINGO_CLINGOPATH "" CACHE STRING "global search directories for clingo's include statement") mark_as_advanced(CLINGO_BUILD_WEB) mark_as_advanced(CLINGO_BUILD_STATIC) mark_as_advanced(CLINGO_BUILD_SHARED) mark_as_advanced(CLINGO_BUILD_PY_SHARED) mark_as_advanced(CLINGO_BUILD_LUA_SHARED) # workaround to set custom ar and ranlib if (CLINGO_CMAKE_AR) set(CMAKE_AR "${CLINGO_CMAKE_AR}") set(CMAKE_CXX_ARCHIVE_CREATE " qc ") set(CMAKE_C_ARCHIVE_CREATE " qc ") endif() if (CLINGO_CMAKE_RANLIB) set(CMAKE_RANLIB "${CLINGO_CMAKE_RANLIB}") set(CMAKE_CXX_ARCHIVE_FINISH " ") set(CMAKE_C_ARCHIVE_FINISH " ") endif() if (CLINGO_MANAGE_RPATH) set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) if ("${isSystemDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") endif() endif() if (CLINGO_BUILD_WEB) unset(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES) unset(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES) unset(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS) unset(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS) unset(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES) unset(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES) endif() if (NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) endif() if (NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) endif() if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) endif() if (NOT CMAKE_IMPORT_LIBRARY_PREFIX) set(CMAKE_IMPORT_LIBRARY_PREFIX import_) endif() # NOTE: searching for the interpreter first increases the chance # that searching for the python libraries finds the matching libraries for the default python interpreter # python is also used to run the tests find_package(PythonInterp) if (CLINGO_BUILD_WITH_PYTHON) if (CLINGO_REQUIRE_PYTHON) find_package(PythonLibs REQUIRED) else() find_package(PythonLibs) endif() if(PYTHONLIBS_FOUND) add_library(Python::Python INTERFACE IMPORTED) set_property(TARGET Python::Python PROPERTY INTERFACE_LINK_LIBRARIES "${PYTHON_LIBRARIES}") set_property(TARGET Python::Python PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}") endif() endif() if (CLINGO_BUILD_WITH_LUA) if (CLINGO_REQUIRE_LUA) find_package(Lua REQUIRED) else() find_package(Lua) endif() if(LUA_FOUND) add_library(Lua::Lua INTERFACE IMPORTED) set_property(TARGET Lua::Lua PROPERTY INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}") set_property(TARGET Lua::Lua PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}") endif() endif() find_package(BISON "2.5") find_package(RE2C "0.13") if (POLICY CMP0063 AND (CLINGO_BUILD_SHARED OR PYTHONLIBS_FOUND OR LUA_FOUND)) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_C_VISIBILITY_PRESET hidden) endif() enable_testing() # NOTE: assumes that submodule has been initialized set(clingo_library_targets libclingo libgringo libpotassco libclasp libreify) set(CLASP_BUILD_APP ${CLINGO_BUILD_APPS} CACHE BOOL "") add_subdirectory(clasp) add_subdirectory(libreify) add_subdirectory(libgringo) add_subdirectory(libclingo) if (PYTHONLIBS_FOUND) add_subdirectory(libpyclingo) list(APPEND clingo_library_targets libpyclingo) else() add_library(libpyclingo INTERFACE IMPORTED) endif() if (LUA_FOUND) add_subdirectory(libluaclingo) list(APPEND clingo_library_targets libluaclingo) else() add_library(libluaclingo INTERFACE IMPORTED) endif() if (CLINGO_BUILD_APPS) add_subdirectory(app/reify) add_subdirectory(app/gringo) add_subdirectory(app/clingo) endif() if (CLINGO_BUILD_EXAMPLES) add_subdirectory(examples/c) add_subdirectory(examples/cc) endif() if (NOT CLINGO_BUILD_STATIC AND PYTHONLIBS_FOUND) add_subdirectory(app/pyclingo) endif() if (NOT CLINGO_BUILD_STATIC AND LUA_FOUND) add_subdirectory(app/luaclingo) endif() if (CLINGO_BUILD_WEB) add_subdirectory(app/web) endif() if (NOT CLINGO_BUILD_STATIC AND (CLINGO_BUILD_SHARED OR PYTHONLIBS_FOUND OR LUA_FOUND)) foreach(target ${clingo_library_targets}) set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE ON) endforeach() endif() clingo-5.2.2/INSTALL.md000066400000000000000000000162021320011352300144120ustar00rootroot00000000000000# Table of Contents - [Requirements](#requirements) - [Development Dependencies](#development-dependencies) - [Optional Dependencies](#optional-dependencies) - [Build, Install, and Test](#build-install-and-test) - [Build Options](#build-options) - [Generic Options](#generic-options) - [Python Support](#python-support) - [Lua Support](#lua-support) - [Troubleshooting](#troubleshooting) - [Notes for Windows Users](#notes-for-windows-users) # Requirements - a c++14 conforming compiler - *at least* [gcc](https://gcc.gnu.org/) version 4.9 - [clang](http://clang.llvm.org/) version 3.1 (using either libstdc++ provided by gcc 4.9 or libc++) - *at least* msvc++ 14.0 ([Visual Studio](https://www.visualstudio.com/) 2015 Update 3) - other compilers might work - the [cmake](https://www.cmake.org/) build system - at least version 3.3 is recommended - at least version 3.1 is *required* ## Development Dependencies The following dependencies are only required when compiling a development branch. Releases already include the necessary generated files. - the [bison](https://www.gnu.org/software/bison/) parser generator - *at least* version 2.5 - version 3.0 produces harmless warnings (to stay backwards-compatible) - the [re2c]() lexer generator - *at least* version 0.13 - version 0.13.5 is used for development ## Optional Dependencies - the [Python](https://www.python.org/) script language - version 2.7 is tested - the [Lua](https://www.lua.org/) script language - version 5.1 is used for development - version 5.2 and 5.3 should work # Build, Install, and Test When cloning the git repository, do not forget to update the submodules (with source releases, you can skip this step): git submodule update --init --recursive To build gringo, clingo, and reify in their default configurations in release mode, run: cmake -H -B -DCMAKE_BUILD_TYPE=Release cmake --build The resulting binaries and shared libraries will be in `/bin` and are ready to use. To install all binaries and development files under cmake's install prefix (see the [build options](#build-options)), run: cmake --build --target install To run the tests, enable option `CLINGO_BUILD_TESTS` (see [build options](#build-options)) and run: cmake --build --target test ## Build Options Cmake's `-L` option can be used to get an overview over the variables that can be set for building gringo/clingo. To get gringo/clingo specific options, run cmake -H -B -DCMAKE_BUILD_TYPE=Release -LH or, to also print important cmake specific configuration variables cmake -H -B -DCMAKE_BUILD_TYPE=Release -LAH Options and variables can be passed to cmake on the command line using `-D=` or by editing `/CMakeCache.txt` after running cmake. The build scripts by default try to detect optional dependencies, like Python and Lua scripting support. Clingo uses [libpotassco](https://github.com/potassco/libpotassco) and [clasp](https://github.com/potassco/potassco). Both components have their own sets of configuration variables: - [building libpotassco](https://github.com/potassco/libpotassco#installation) - [building clasp](https://github.com/potassco/clasp#building--installing) In the following, the most important options to control the build are listed. ### Generic Options - Variable `CMAKE_BUILD_TYPE` should be set to `Release`. - Variable `CMAKE_INSTALL_PREFIX` controls where to install clingo. - Option `CLINGO_BUILD_APPS` controls whether to build the applications gringo, clingo, and reify. (Default: `ON`) - Option `CLINGO_BUILD_EXAMPLES` controls whether to build the clingo API examples. (Default: `OFF`) - Option `CLINGO_BUILD_TESTS` controls whether to build the clingo tests and enable the test target running unit as well as acceptance tests. (Default: `OFF`) - Option `CLINGO_MANAGE_RPATH` controls how to find libraries on platforms where this is supported, like Linux, macOS, or BSD but not Windows. This option should be enabled if clingo is installed in a non-default location, like the users home directory; otherwise it has no effect. (Default: `ON`) ### Python Support With the default configuration, Python support will be auto-detected if the Python development packages are installed. - Option `CLINGO_BUILD_WITH_PYTHON` can be used to enable or disable Python support. (Default: `ON`) - If option `CLINGO_REQUIRE_PYTHON` is enabled, configuration will fail if no Python support is detected; otherwise, Python support will simply be disabled if not detected. (Default: `OFF`) - If option `PYCLINGO_USER_INSTALL` is enabled, the clingo Python module is installed in the users home directory; otherwise it is installed in the system's Python library directory. (Default: `ON`) - Variable `PYCLINGO_INSTALL_DIR` can be used to customize where to install the python module. (Default: automatically detected) Note that it can happen that the found Python interpreter does not match the found Python libraries if the development headers for the interpreter are not installed. Make sure to install them before running cmake (or remove or adjust the `CMakeCache.txt` file). It is also possible to explicitely select a Python installation by pointing the variable `PYTHON_EXECUTABLE` to the desired Python interpreter. ### Lua Support With the default configuration, Lua support will be auto-detected if the Lua development packages are installed. - Option `CLINGO_BUILD_WITH_LUA` can be used to enable or disable Lua support. (Default: `ON`) - If option `CLINGO_REQUIRE_LUA` is enabled, configuration will fail if no Lua support is detected; otherwise, Lua support will simply be disabled if not detected. (Default: `OFF`) - If variable `LUACLINGO_INSTALL_DIR` is set, the clingo lua module will be installed there. (Default: not set) # Troubleshooting After installing the required packages clingo should compile on most \*nixes. If a dependency is missing or a software version too old, then there are typically community repositories that provide the necessary packages. To list a few: - the [ToolChain](https://wiki.ubuntu.com/ToolChain) repository for Ubuntu 14.04 and earlier (later versions should include all required packages) - the [Developer Toolset](https://wiki.centos.org/SpecialInterestGroup/SCLo/CollectionsList) for CentOS - the [Cygwin](http://cygwin.org) project under Windows (re2c must be compiled by hand) - both [Homebrew](https://brew.sh/) and [MacPorts](https://www.macports.org/) provide all the software necessary to compile clingo And, well, you can compile a recent gcc version yourself. Even on ancient Linux systems. ;) ## Notes for Windows Users clingo can be compiled using the [Mingw-w64](https://mingw-w64.sourceforge.net/) compiler, the Cygwin project, or Visual Studio 2015 Update 3. For development, [bison](http://cs.uni-potsdam.de/~kaminski/win_flex_bison-latest.zip) from the [Win flex-bison](https://sourceforge.net/projects/winflexbison/) project and a self compiled [re2c](http://cs.uni-potsdam.de/~kaminski/re2c.exe) executable can be used. clingo-5.2.2/LICENSE.md000066400000000000000000000020701320011352300143640ustar00rootroot00000000000000# The MIT License (MIT) Copyright 2017 Roland Kaminski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. clingo-5.2.2/README.md000066400000000000000000000017411320011352300142430ustar00rootroot00000000000000# Clingo: A grounder and solver for logic programs Clingo is part of the [Potassco](https://potassco.org) project for *Answer Set Programming* (ASP). ASP offers a simple and powerful modeling language to describe combinatorial problems as *logic programs*. The *clingo* system then takes such a logic program and computes *answer sets* representing solutions to the given problem. To get an idea, check our [Getting Started](https://potassco.org/doc/start/) page and the [online version](https://potassco.org/clingo/run/) of clingo. Please consult the following resources for further information: - [**Downloading source and binary releases**](https://github.com/potassco/clingo/releases) - [**Installation and software requirements**](INSTALL.md) - [Changes between releases](CHANGES.md) - [Documentation](http://sourceforge.net/projects/potassco/files/guide/) - [Potassco clingo page](https://potassco.org/clingo/) Clingo is distributed under the [MIT License](LICENSE.md). clingo-5.2.2/app/000077500000000000000000000000001320011352300135415ustar00rootroot00000000000000clingo-5.2.2/app/clingo/000077500000000000000000000000001320011352300150145ustar00rootroot00000000000000clingo-5.2.2/app/clingo/CMakeLists.txt000066400000000000000000000007731320011352300175630ustar00rootroot00000000000000# [[[source: . set(ide_source_group "Source Files") set(source-group "${CMAKE_CURRENT_SOURCE_DIR}/main.cc") source_group("${ide_source_group}" FILES ${source-group}) set(source ${source-group}) # ]]] add_executable(clingo ${header} ${source}) target_link_libraries(clingo PRIVATE libclingo libpyclingo libluaclingo) set_target_properties(clingo PROPERTIES FOLDER exe) install(TARGETS clingo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if (CLINGO_BUILD_TESTS) add_subdirectory(tests) endif() clingo-5.2.2/app/clingo/main.cc000066400000000000000000000033411320011352300162500ustar00rootroot00000000000000// {{{ MIT License // Copyright 2017 Roland Kaminski // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // }}} #ifdef CLINGO_WITH_PYTHON # include #endif #ifdef CLINGO_WITH_LUA # include #endif #include #include extern "C" CLINGO_VISIBILITY_DEFAULT int clingo_main_(int argc, char *argv[]); int main(int argc, char** argv) { # ifdef CLINGO_WITH_PYTHON if (!clingo_register_python_()) { std::cerr << clingo_error_message() << std::endl; return 1; } # endif # ifdef CLINGO_WITH_LUA if (!clingo_register_lua_(nullptr)) { std::cerr << clingo_error_message() << std::endl; return 1; } # endif return clingo_main_(argc, argv); } clingo-5.2.2/app/clingo/tests/000077500000000000000000000000001320011352300161565ustar00rootroot00000000000000clingo-5.2.2/app/clingo/tests/CMakeLists.txt000066400000000000000000000004301320011352300207130ustar00rootroot00000000000000enable_testing() if (PYTHON_EXECUTABLE) if (CLASP_BUILD_WITH_THREADS) set(solver-options "-t8") endif() add_test(NAME test_clingo_app COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/run.py" -c $ run -- ${solver-options}) endif() clingo-5.2.2/app/clingo/tests/lp/000077500000000000000000000000001320011352300165715ustar00rootroot00000000000000clingo-5.2.2/app/clingo/tests/lp/aggregates.lp000066400000000000000000000070151320011352300212420ustar00rootroot00000000000000arg(s3). sat(s3):-ass(s3,Y_s3),lt(Y_s3,Z_s3),V_t_0=0, V_3_1=-V_t_0, V_t_2=0, V_2_1=-2*V_t_2+V_3_1, dom(V_t_3), V_t_3 #sum{Z_s3,s3}V_t_3, V_1_1=1*V_t_3+V_2_1, V_t_4=0, V_0_1=2*V_t_4+V_1_1, dom(V_1), V_1 #sum{1:V_0_1>0} V_1, V_1=1. inv(s3):-ass(s3,Y_s3),lt(Y_s3,Z_s3),V_t_0=0, V_3_1=-V_t_0, V_t_2=0, V_2_1=-2*V_t_2+V_3_1, dom(V_t_3), V_t_3 #sum{Z_s3,s3} V_t_3, V_1_1=1*V_t_3+V_2_1, V_t_4=0, V_0_1=2*V_t_4+V_1_1, dom(V_1), V_1 #sum{1:V_0_1>0}V_1, V_1=0. sattwo(s3):-asstwo(s3,Y_s3),lt(Y_s3,Z_s3),V_t_0=0, V_3_1=-V_t_0, V_t_2=0, V_2_1=-2*V_t_2+V_3_1, dom(V_t_3), V_t_3#sum{Z_s3,s3}V_t_3, V_1_1=1*V_t_3+V_2_1, V_t_4=0, V_0_1=2*V_t_4+V_1_1, dom(V_1), V_1 #sum{1:V_0_1>0}V_1, V_1=1. invtwo(s3):-asstwo(s3,Y_s3),lt(Y_s3,Z_s3),V_t_0=0, V_3_1=-V_t_0, V_t_2=0, V_2_1=-2*V_t_2+V_3_1, dom(V_t_3), V_t_3#sum{Z_s3,s3}V_t_3, V_1_1=1*V_t_3+V_2_1, V_t_4=0, V_0_1=2*V_t_4+V_1_1, dom(V_1), V_1 #sum{1:V_0_1>0}V_1, V_1=0. arg(s2). sat(s2):-V_t_5=0, V_3_6=-V_t_5, V_t_7=0, V_2_6=-2*V_t_7+V_3_6, V_t_8=0, V_1_6=1*V_t_8+V_2_6, V_t_9=0, V_0_6=2*V_t_9+V_1_6, dom(V_6), V_6#sum{1:V_0_6>0}V_6, V_6=1. inv(s2):-V_t_5=0, V_3_6=-V_t_5, V_t_7=0, V_2_6=-2*V_t_7+V_3_6, V_t_8=0, V_1_6=1*V_t_8+V_2_6, V_t_9=0, V_0_6=2*V_t_9+V_1_6, dom(V_6), V_6#sum{1:V_0_6>0}V_6, V_6=0. sattwo(s2):-V_t_5=0, V_3_6=-V_t_5, V_t_7=0, V_2_6=-2*V_t_7+V_3_6, V_t_8=0, V_1_6=1*V_t_8+V_2_6, V_t_9=0, V_0_6=2*V_t_9+V_1_6, dom(V_6), V_6#sum{1:V_0_6>0}V_6, V_6=1. invtwo(s2):-V_t_5=0, V_3_6=-V_t_5, V_t_7=0, V_2_6=-2*V_t_7+V_3_6, V_t_8=0, V_1_6=1*V_t_8+V_2_6, V_t_9=0, V_0_6=2*V_t_9+V_1_6, dom(V_6), V_6#sum{1:V_0_6>0}V_6, V_6=0. arg(s1). sat(s1):-ass(s2,Y_s2),lt(Y_s2,Z_s2),ass(s3,Y_s3),lt(Y_s3,Z_s3),dom(V_t_10), V_t_10#sum{Z_s2,s2}V_t_10, V_3_11=-V_t_10, V_t_12=0, V_2_11=-2*V_t_12+V_3_11, dom(V_t_13), V_t_13 #sum{Z_s3,s3}V_t_13, V_1_11=1*V_t_13+V_2_11, V_t_14=0, V_0_11=2*V_t_14+V_1_11, dom(V_11), V_11#sum{1:V_0_11>0}V_11, V_11=1. inv(s1):-ass(s2,Y_s2),lt(Y_s2,Z_s2),ass(s3,Y_s3),lt(Y_s3,Z_s3),dom(V_t_10), V_t_10#sum{Z_s2,s2}V_t_10, V_3_11=-V_t_10, V_t_12=0, V_2_11=-2*V_t_12+V_3_11, dom(V_t_13), V_t_13 #sum{Z_s3,s3}V_t_13, V_1_11=1*V_t_13+V_2_11, V_t_14=0, V_0_11=2*V_t_14+V_1_11, dom(V_11), V_11#sum{1:V_0_11>0}V_11, V_11=0. sattwo(s1):-asstwo(s2,Y_s2),lt(Y_s2,Z_s2),asstwo(s3,Y_s3),lt(Y_s3,Z_s3),dom(V_t_10), V_t_10#sum{Z_s2,s2}V_t_10, V_3_11=-V_t_10, V_t_12=0, V_2_11=-2*V_t_12+V_3_11, dom(V_t_13), V_t_13#sum{Z_s3,s3}V_t_13, V_1_11=1*V_t_13+V_2_11, V_t_14=0, V_0_11=2*V_t_14+V_1_11, dom(V_11), V_11#sum{1:V_0_11>0}V_11, V_11=1. invtwo(s1):-asstwo(s2,Y_s2),lt(Y_s2,Z_s2),asstwo(s3,Y_s3),lt(Y_s3,Z_s3),dom(V_t_10), V_t_10#sum{Z_s2,s2}V_t_10, V_3_11=-V_t_10, V_t_12=0, V_2_11=-2*V_t_12+V_3_11, dom(V_t_13), V_t_13#sum{Z_s3,s3}V_t_13, V_1_11=1*V_t_13+V_2_11, V_t_14=0, V_0_11=2*V_t_14+V_1_11, dom(V_11), V_11#sum{1:V_0_11>0}V_11, V_11=0. saturate:-ass(s3,X_1),asstwo(s3,X_1),ass(s2,X_2),asstwo(s2,X_2),ass(s1,X_3),asstwo(s1,X_3). dom(0..1). lt(u,0).lt(u,1).lt(1,1).lt(0,0). ass(S,0):-not ass(S,1),not ass(S,u),arg(S). ass(S,1):-not ass(S,u),not ass(S,0),arg(S). ass(S,u):-not ass(S,0),not ass(S,1),arg(S). :-arg(S),ass(S,1),inv(S). :-arg(S),ass(S,0),sat(S). asstwo(S,0):-ass(S,0). asstwo(S,1):-ass(S,1). asstwo(S,0)|asstwo(S,1)|asstwo(S,u):-ass(S,u). saturate:-arg(S),asstwo(S,1),invtwo(S). saturate:-arg(S),asstwo(S,0),sattwo(S). asstwo(S,0):-arg(S),ass(S,u),saturate. asstwo(S,1):-arg(S),ass(S,u),saturate. asstwo(S,u):-arg(S),ass(S,u),saturate. sattwo(S):-arg(S),ass(S,u),saturate. :-not saturate. #show ass/2. :-ass(s1, 0),ass(s2, 0),ass(s3, 0). :-ass(s1, 1),ass(s2, 0),ass(s3, 1). %unfounded: saturate, asstwo(s1,0), asstwo(s1,0)clingo-5.2.2/app/clingo/tests/lp/aggregates.sol000066400000000000000000000000161320011352300214160ustar00rootroot00000000000000Step: 1 UNSAT clingo-5.2.2/app/clingo/tests/lp/bio.cmd000066400000000000000000000000261320011352300200250ustar00rootroot00000000000000--opt-mode=optN -q1,1 clingo-5.2.2/app/clingo/tests/lp/bio.lp000066400000000000000000000012641320011352300177020ustar00rootroot00000000000000#const h=3. time(0..h). volume(1..10). 0 $<= $b(T) $<= 20 :- time(T). 0 $<= $f(T) $<= 20 :- time(T). 1 $<= $m $<= 16. $b(0) $= 10. $f(0) $= 10. $b(T) $= 2 $* $b(T-1) $- $m :- time(T), T>0. $f(T) $= $f(T-1) $- $b(T-1) :- time(T), T>0, not exogenous(T). $f(T) $= $f(T-1) $- $b(T-1) $+ V :- add(V,T), volume(V), time(T), T>0. { add(V,T) : volume(V) } 1 :- time(T), T>0. exogenous(T) :- add(V,T). #minimize{ 1@2,T : exogenous(T) }. #minimize{ V@1,T : add(V,T) }. #minimize{ 1@3,X : $m $>= X, X=1..16 }. query(T) :- $b(T) $>10, $f(T) $<5, time(T), T>0. % query(T) :- $b(T) $> 10, time(T), T>0. :- not query(h). #show. #show $b/1. #show $f/1. #show add/2. #show $m/0. clingo-5.2.2/app/clingo/tests/lp/bio.sol000066400000000000000000000051021320011352300200570ustar00rootroot00000000000000Step: 1 add(10,1) add(10,2) add(4,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=9 f(3)=0 m=9 add(10,1) add(10,3) add(4,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=3 f(3)=0 m=9 add(10,1) add(5,2) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=4 f(3)=0 m=9 add(10,1) add(5,3) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=8 f(3)=0 m=9 add(10,1) add(6,2) add(8,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=5 f(3)=0 m=9 add(10,1) add(6,3) add(8,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=7 f(3)=0 m=9 add(10,1) add(7,2) add(7,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=6 f(3)=0 m=9 add(10,2) add(10,3) add(4,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=4 f(2)=3 f(3)=0 m=9 add(10,2) add(5,1) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=5 f(2)=4 f(3)=0 m=9 add(10,2) add(5,3) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=8 f(3)=0 m=9 add(10,2) add(6,1) add(8,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=6 f(2)=5 f(3)=0 m=9 add(10,2) add(6,3) add(8,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=7 f(3)=0 m=9 add(10,2) add(7,1) add(7,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=6 f(3)=0 m=9 add(10,3) add(5,1) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=5 f(2)=3 f(3)=0 m=9 add(10,3) add(5,2) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=3 f(3)=0 m=9 add(10,3) add(6,1) add(8,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=6 f(2)=3 f(3)=0 m=9 add(10,3) add(6,2) add(8,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=3 f(3)=0 m=9 add(10,3) add(7,1) add(7,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=3 f(3)=0 m=9 add(6,1) add(9,2) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=6 f(2)=4 f(3)=0 m=9 add(6,2) add(9,1) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=4 f(3)=0 m=9 add(6,3) add(9,1) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=7 f(3)=0 m=9 add(7,1) add(8,2) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=4 f(3)=0 m=9 add(7,1) add(8,3) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=5 f(3)=0 m=9 add(7,2) add(8,1) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=4 f(3)=0 m=9 add(7,2) add(8,3) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=5 f(3)=0 m=9 add(7,3) add(8,1) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=6 f(3)=0 m=9 add(7,3) add(8,2) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=6 f(3)=0 m=9 add(8,1) add(8,2) add(8,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=5 f(3)=0 m=9 OPTIMUM FOUND clingo-5.2.2/app/clingo/tests/lp/elevator.lp000066400000000000000000000036421320011352300207540ustar00rootroot00000000000000#const f = 3. #const a = 1. #const s = 2. #include . #program base. a(e(1)). f(1). f(2). f(3). i(a(e(1),2)). i(y(z(1),3)). i(y(c(up),1)). dir( 1). dir(-1). t(F) :- i(y(z(E),F)). u(F) :- i(y(c(D),F)). e(F) :- u(F), not t(F). g(e(E),F, 1) :- i(y(z(E),F)), i(a(e(E),G)), G < F. g(e(E),F,-1) :- i(y(z(E),F)), i(a(e(E),G)), F < G. g(A,D) :- g(A,F,D). g(A) :- g(A,D). r(A,F) :- g(A,F,D). r(A,F) :- a(A), e(F). l(A,F, 1) :- i(a(A,G)), F != #inf, F = #max{H : r(A,H), G < H}. l(A,F,-1) :- i(a(A,G)), F != #sup, F = #min{H : r(A,H), H < G}. l(A,D) :- l(A,F,D). p(A,-1) :- l(A,-1), l(A,1), not g(A). p(A,-1) :- l(A,-1), g(A,1). p(A, 1) :- g(A,-1), l(A,1), not g(A,1). c(A,F,D) :- l(A,L,D), f(F), i(a(A,G)), H = D*F, D*G < H, H <= D*L. c(A,F,D) :- l(A,L,-D), f(F), i(a(A,G)), H = D*F, D*L < H, H <= D*G, p(A,D). { a(A,F) : a(A) } = 1 :- e(F). t(A,F) :- a(A,F). t(e(E),F) :- i(y(z(E),F)). o(A,F,D) :- t(A,F), i(a(A,G)), dir(D), D*G < D*F. o(A,F,D) :- o(A,F+D,D), i(a(A,G)), c(A,F,D), D*G < D*F. o(A,F,D) :- o(A,G+D,D), i(a(A,G)), c(A,F,D), o(A,F-D,-D), p(A,D). x(A, 1,0) :- g(A, 1). x(A,-1,0) :- g(A,-1), not g(A,1). x(A, 1,0) :- i(a(A,F)), o(A,F+1, 1), not g(A). x(A,-1,0) :- i(a(A,F)), o(A,F-1,-1), not g(A), not o(A,F+1,1). h(X,0) :- i(X). #program step(t). c(A,F,t) :- h(a(A,F),t-1), t(A,F), u(F). c(F,t) :- c(A,F,t). d(e(E),s,t) :- h(y(z(E),F),t-1), h(a(e(E),F),t-1). d(A,s,t):- h(y(c(D),F),t-1), c(A,F,t), e(F). d(A,m(D),t) :- x(A,D,t-1), not d(A,s,t). h(y(z(E),F),t) :- h(y(z(E),F),t-1), not h(a(e(E),F),t-1). h(y(c(D),F),t) :- h(y(c(D),F),t-1), not c(F,t). h(a(A,F),t) :- h(a(A,F-D),t-1), d(A,m(D),t), c(A,F,D). h(a(A,F),t) :- h(a(A,F),t-1), not h(a(A,F+1),t), not h(a(A,F-1),t). x(A,D,t) :- h(a(A,F),t-1), o(A,F+D,D), x(A,D,t-1). x(A,D,t) :- h(a(A,F),t-1), o(A,G+D,D), p(A,D), i(a(A,G)), D*F < D*G, not o(A,F-D,-D). #program check(t). :- query(t), t < 1. #show. #show h/2. clingo-5.2.2/app/clingo/tests/lp/elevator.sol000066400000000000000000000001601320011352300211260ustar00rootroot00000000000000Step: 1 Step: 2 h(a(e(1),2),0) h(a(e(1),3),1) h(y(c(up),1),0) h(y(c(up),1),1) h(y(z(1),3),0) h(y(z(1),3),1) SAT clingo-5.2.2/app/clingo/tests/lp/istop.lp000066400000000000000000000001011320011352300202540ustar00rootroot00000000000000#include . #const istop="UNSAT". #program base. :- . clingo-5.2.2/app/clingo/tests/lp/istop.sol000066400000000000000000000000161320011352300204430ustar00rootroot00000000000000Step: 1 UNSAT clingo-5.2.2/app/clingo/tests/lp/project.cmd000066400000000000000000000000121320011352300207150ustar00rootroot00000000000000--project clingo-5.2.2/app/clingo/tests/lp/project.lp000066400000000000000000000000771320011352300206000ustar00rootroot00000000000000#project p(X). #show p/1. 1 { p(1..2) } 1. 1 { q(1..2) } 1. clingo-5.2.2/app/clingo/tests/lp/project.sol000066400000000000000000000000261320011352300207540ustar00rootroot00000000000000Step: 1 p(1) p(2) SAT clingo-5.2.2/app/clingo/tests/lp/show.lp000066400000000000000000000003021320011352300201010ustar00rootroot00000000000000#include . #show show/0. #const imin=4. 1 { p(1..4) } 1. #show p(X) : p(X). #program step(k). q(k+1), k < 3. :- p(X), q(X), k < 3. {show} :- k == 3. #show p(1..4) : show, k == 3. clingo-5.2.2/app/clingo/tests/lp/show.sol000066400000000000000000000003301320011352300202640ustar00rootroot00000000000000Step: 1 p(1) p(2) p(3) p(4) Step: 2 p(1) p(2) p(3) p(4) Step: 3 p(1) p(2) p(3) p(4) Step: 4 p(1) p(1) p(2) p(3) p(4) show p(1) p(2) p(3) p(4) show p(1) p(2) p(3) p(4) show p(1) p(2) p(3) p(4) show p(2) p(3) p(4) SAT clingo-5.2.2/app/clingo/tests/lp/subset.cmd000066400000000000000000000000231320011352300205560ustar00rootroot00000000000000--heuristic=domain clingo-5.2.2/app/clingo/tests/lp/subset.lp000066400000000000000000000004071320011352300204340ustar00rootroot00000000000000#heuristic p(1..2). [1,false] #heuristic p(2..3). [2@1,true] #heuristic p(3..4). [1,sign] #heuristic p(4..5). [2@3,level] #heuristic p(5..6). [3@4,factor] #heuristic p(6..7). [3@4,init] 3 { p(1..10) }. 2 { p(1..5) }. 4 { p(3..8) }. 2 { p(7..9) }. 3 { p(2..9) }. clingo-5.2.2/app/clingo/tests/lp/subset.sol000066400000000000000000000201221320011352300206120ustar00rootroot00000000000000Step: 1 p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(9) p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(8) p(9) p(1) p(10) p(2) p(3) p(4) p(5) p(7) p(8) p(1) p(10) p(2) p(3) p(4) p(5) p(7) p(8) p(9) p(1) p(10) p(2) p(3) p(4) p(5) p(7) p(9) p(1) p(10) p(2) p(3) p(4) p(5) p(8) p(9) p(1) p(10) p(2) p(3) p(4) p(6) p(7) p(8) p(1) p(10) p(2) p(3) p(4) p(6) p(7) p(8) p(9) p(1) p(10) p(2) p(3) p(4) p(6) p(7) p(9) p(1) p(10) p(2) p(3) p(4) p(6) p(8) p(9) p(1) p(10) p(2) p(3) p(4) p(7) p(8) p(1) p(10) p(2) p(3) p(4) p(7) p(8) p(9) p(1) p(10) p(2) p(3) p(5) p(6) p(7) p(8) p(1) p(10) p(2) p(3) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(2) p(3) p(5) p(6) p(7) p(9) p(1) p(10) p(2) p(3) p(5) p(6) p(8) p(9) p(1) p(10) p(2) p(3) p(5) p(7) p(8) p(1) p(10) p(2) p(3) p(5) p(7) p(8) p(9) p(1) p(10) p(2) p(3) p(6) p(7) p(8) p(1) p(10) p(2) p(3) p(6) p(7) p(8) p(9) p(1) p(10) p(2) p(4) p(5) p(6) p(7) p(8) p(1) p(10) p(2) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(2) p(4) p(5) p(6) p(7) p(9) p(1) p(10) p(2) p(4) p(5) p(6) p(8) p(9) p(1) p(10) p(2) p(4) p(5) p(7) p(8) p(1) p(10) p(2) p(4) p(5) p(7) p(8) p(9) p(1) p(10) p(2) p(4) p(6) p(7) p(8) p(1) p(10) p(2) p(4) p(6) p(7) p(8) p(9) p(1) p(10) p(2) p(5) p(6) p(7) p(8) p(1) p(10) p(2) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(3) p(4) p(5) p(6) p(7) p(8) p(1) p(10) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(3) p(4) p(5) p(6) p(7) p(9) p(1) p(10) p(3) p(4) p(5) p(6) p(8) p(9) p(1) p(10) p(3) p(4) p(5) p(7) p(8) p(1) p(10) p(3) p(4) p(5) p(7) p(8) p(9) p(1) p(10) p(3) p(4) p(5) p(7) p(9) p(1) p(10) p(3) p(4) p(5) p(8) p(9) p(1) p(10) p(3) p(4) p(6) p(7) p(8) p(1) p(10) p(3) p(4) p(6) p(7) p(8) p(9) p(1) p(10) p(3) p(4) p(6) p(7) p(9) p(1) p(10) p(3) p(4) p(6) p(8) p(9) p(1) p(10) p(3) p(4) p(7) p(8) p(1) p(10) p(3) p(4) p(7) p(8) p(9) p(1) p(10) p(3) p(5) p(6) p(7) p(8) p(1) p(10) p(3) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(3) p(5) p(6) p(7) p(9) p(1) p(10) p(3) p(5) p(6) p(8) p(9) p(1) p(10) p(3) p(5) p(7) p(8) p(1) p(10) p(3) p(5) p(7) p(8) p(9) p(1) p(10) p(3) p(6) p(7) p(8) p(1) p(10) p(3) p(6) p(7) p(8) p(9) p(1) p(10) p(4) p(5) p(6) p(7) p(8) p(1) p(10) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(10) p(4) p(5) p(6) p(7) p(9) p(1) p(10) p(4) p(5) p(6) p(8) p(9) p(1) p(10) p(4) p(5) p(7) p(8) p(1) p(10) p(4) p(5) p(7) p(8) p(9) p(1) p(10) p(4) p(6) p(7) p(8) p(1) p(10) p(4) p(6) p(7) p(8) p(9) p(1) p(10) p(5) p(6) p(7) p(8) p(1) p(10) p(5) p(6) p(7) p(8) p(9) p(1) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(1) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(2) p(3) p(4) p(5) p(6) p(7) p(9) p(1) p(2) p(3) p(4) p(5) p(6) p(8) p(9) p(1) p(2) p(3) p(4) p(5) p(7) p(8) p(1) p(2) p(3) p(4) p(5) p(7) p(8) p(9) p(1) p(2) p(3) p(4) p(5) p(7) p(9) p(1) p(2) p(3) p(4) p(5) p(8) p(9) p(1) p(2) p(3) p(4) p(6) p(7) p(8) p(1) p(2) p(3) p(4) p(6) p(7) p(8) p(9) p(1) p(2) p(3) p(4) p(6) p(7) p(9) p(1) p(2) p(3) p(4) p(6) p(8) p(9) p(1) p(2) p(3) p(4) p(7) p(8) p(1) p(2) p(3) p(4) p(7) p(8) p(9) p(1) p(2) p(3) p(5) p(6) p(7) p(8) p(1) p(2) p(3) p(5) p(6) p(7) p(8) p(9) p(1) p(2) p(3) p(5) p(6) p(7) p(9) p(1) p(2) p(3) p(5) p(6) p(8) p(9) p(1) p(2) p(3) p(5) p(7) p(8) p(1) p(2) p(3) p(5) p(7) p(8) p(9) p(1) p(2) p(3) p(6) p(7) p(8) p(1) p(2) p(3) p(6) p(7) p(8) p(9) p(1) p(2) p(4) p(5) p(6) p(7) p(8) p(1) p(2) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(2) p(4) p(5) p(6) p(7) p(9) p(1) p(2) p(4) p(5) p(6) p(8) p(9) p(1) p(2) p(4) p(5) p(7) p(8) p(1) p(2) p(4) p(5) p(7) p(8) p(9) p(1) p(2) p(4) p(6) p(7) p(8) p(1) p(2) p(4) p(6) p(7) p(8) p(9) p(1) p(2) p(5) p(6) p(7) p(8) p(1) p(2) p(5) p(6) p(7) p(8) p(9) p(1) p(3) p(4) p(5) p(6) p(7) p(8) p(1) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(3) p(4) p(5) p(6) p(7) p(9) p(1) p(3) p(4) p(5) p(6) p(8) p(9) p(1) p(3) p(4) p(5) p(7) p(8) p(1) p(3) p(4) p(5) p(7) p(8) p(9) p(1) p(3) p(4) p(5) p(7) p(9) p(1) p(3) p(4) p(5) p(8) p(9) p(1) p(3) p(4) p(6) p(7) p(8) p(1) p(3) p(4) p(6) p(7) p(8) p(9) p(1) p(3) p(4) p(6) p(7) p(9) p(1) p(3) p(4) p(6) p(8) p(9) p(1) p(3) p(4) p(7) p(8) p(1) p(3) p(4) p(7) p(8) p(9) p(1) p(3) p(5) p(6) p(7) p(8) p(1) p(3) p(5) p(6) p(7) p(8) p(9) p(1) p(3) p(5) p(6) p(7) p(9) p(1) p(3) p(5) p(6) p(8) p(9) p(1) p(3) p(5) p(7) p(8) p(1) p(3) p(5) p(7) p(8) p(9) p(1) p(3) p(6) p(7) p(8) p(1) p(3) p(6) p(7) p(8) p(9) p(1) p(4) p(5) p(6) p(7) p(8) p(1) p(4) p(5) p(6) p(7) p(8) p(9) p(1) p(4) p(5) p(6) p(7) p(9) p(1) p(4) p(5) p(6) p(8) p(9) p(1) p(4) p(5) p(7) p(8) p(1) p(4) p(5) p(7) p(8) p(9) p(1) p(4) p(6) p(7) p(8) p(1) p(4) p(6) p(7) p(8) p(9) p(1) p(5) p(6) p(7) p(8) p(1) p(5) p(6) p(7) p(8) p(9) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(9) p(10) p(2) p(3) p(4) p(5) p(6) p(8) p(9) p(10) p(2) p(3) p(4) p(5) p(7) p(8) p(10) p(2) p(3) p(4) p(5) p(7) p(8) p(9) p(10) p(2) p(3) p(4) p(5) p(7) p(9) p(10) p(2) p(3) p(4) p(5) p(8) p(9) p(10) p(2) p(3) p(4) p(6) p(7) p(8) p(10) p(2) p(3) p(4) p(6) p(7) p(8) p(9) p(10) p(2) p(3) p(4) p(6) p(7) p(9) p(10) p(2) p(3) p(4) p(6) p(8) p(9) p(10) p(2) p(3) p(4) p(7) p(8) p(10) p(2) p(3) p(4) p(7) p(8) p(9) p(10) p(2) p(3) p(5) p(6) p(7) p(8) p(10) p(2) p(3) p(5) p(6) p(7) p(8) p(9) p(10) p(2) p(3) p(5) p(6) p(7) p(9) p(10) p(2) p(3) p(5) p(6) p(8) p(9) p(10) p(2) p(3) p(5) p(7) p(8) p(10) p(2) p(3) p(5) p(7) p(8) p(9) p(10) p(2) p(3) p(6) p(7) p(8) p(10) p(2) p(3) p(6) p(7) p(8) p(9) p(10) p(2) p(4) p(5) p(6) p(7) p(8) p(10) p(2) p(4) p(5) p(6) p(7) p(8) p(9) p(10) p(2) p(4) p(5) p(6) p(7) p(9) p(10) p(2) p(4) p(5) p(6) p(8) p(9) p(10) p(2) p(4) p(5) p(7) p(8) p(10) p(2) p(4) p(5) p(7) p(8) p(9) p(10) p(2) p(4) p(6) p(7) p(8) p(10) p(2) p(4) p(6) p(7) p(8) p(9) p(10) p(2) p(5) p(6) p(7) p(8) p(10) p(2) p(5) p(6) p(7) p(8) p(9) p(10) p(3) p(4) p(5) p(6) p(7) p(8) p(10) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(10) p(3) p(4) p(5) p(6) p(7) p(9) p(10) p(3) p(4) p(5) p(6) p(8) p(9) p(10) p(3) p(4) p(5) p(7) p(8) p(10) p(3) p(4) p(5) p(7) p(8) p(9) p(10) p(3) p(4) p(5) p(7) p(9) p(10) p(3) p(4) p(5) p(8) p(9) p(10) p(3) p(4) p(6) p(7) p(8) p(10) p(3) p(4) p(6) p(7) p(8) p(9) p(10) p(3) p(4) p(6) p(7) p(9) p(10) p(3) p(4) p(6) p(8) p(9) p(10) p(3) p(4) p(7) p(8) p(10) p(3) p(4) p(7) p(8) p(9) p(10) p(3) p(5) p(6) p(7) p(8) p(10) p(3) p(5) p(6) p(7) p(8) p(9) p(10) p(3) p(5) p(6) p(7) p(9) p(10) p(3) p(5) p(6) p(8) p(9) p(10) p(3) p(5) p(7) p(8) p(10) p(3) p(5) p(7) p(8) p(9) p(10) p(4) p(5) p(6) p(7) p(8) p(10) p(4) p(5) p(6) p(7) p(8) p(9) p(10) p(4) p(5) p(6) p(7) p(9) p(10) p(4) p(5) p(6) p(8) p(9) p(10) p(4) p(5) p(7) p(8) p(10) p(4) p(5) p(7) p(8) p(9) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(2) p(3) p(4) p(5) p(6) p(7) p(9) p(2) p(3) p(4) p(5) p(6) p(8) p(9) p(2) p(3) p(4) p(5) p(7) p(8) p(2) p(3) p(4) p(5) p(7) p(8) p(9) p(2) p(3) p(4) p(5) p(7) p(9) p(2) p(3) p(4) p(5) p(8) p(9) p(2) p(3) p(4) p(6) p(7) p(8) p(2) p(3) p(4) p(6) p(7) p(8) p(9) p(2) p(3) p(4) p(6) p(7) p(9) p(2) p(3) p(4) p(6) p(8) p(9) p(2) p(3) p(4) p(7) p(8) p(2) p(3) p(4) p(7) p(8) p(9) p(2) p(3) p(5) p(6) p(7) p(8) p(2) p(3) p(5) p(6) p(7) p(8) p(9) p(2) p(3) p(5) p(6) p(7) p(9) p(2) p(3) p(5) p(6) p(8) p(9) p(2) p(3) p(5) p(7) p(8) p(2) p(3) p(5) p(7) p(8) p(9) p(2) p(3) p(6) p(7) p(8) p(2) p(3) p(6) p(7) p(8) p(9) p(2) p(4) p(5) p(6) p(7) p(8) p(2) p(4) p(5) p(6) p(7) p(8) p(9) p(2) p(4) p(5) p(6) p(7) p(9) p(2) p(4) p(5) p(6) p(8) p(9) p(2) p(4) p(5) p(7) p(8) p(2) p(4) p(5) p(7) p(8) p(9) p(2) p(4) p(6) p(7) p(8) p(2) p(4) p(6) p(7) p(8) p(9) p(2) p(5) p(6) p(7) p(8) p(2) p(5) p(6) p(7) p(8) p(9) p(3) p(4) p(5) p(6) p(7) p(8) p(3) p(4) p(5) p(6) p(7) p(8) p(9) p(3) p(4) p(5) p(6) p(7) p(9) p(3) p(4) p(5) p(6) p(8) p(9) p(3) p(4) p(5) p(7) p(8) p(3) p(4) p(5) p(7) p(8) p(9) p(3) p(4) p(5) p(7) p(9) p(3) p(4) p(5) p(8) p(9) p(3) p(4) p(6) p(7) p(8) p(3) p(4) p(6) p(7) p(8) p(9) p(3) p(4) p(6) p(7) p(9) p(3) p(4) p(6) p(8) p(9) p(3) p(4) p(7) p(8) p(3) p(4) p(7) p(8) p(9) p(3) p(5) p(6) p(7) p(8) p(3) p(5) p(6) p(7) p(8) p(9) p(3) p(5) p(6) p(7) p(9) p(3) p(5) p(6) p(8) p(9) p(3) p(5) p(7) p(8) p(3) p(5) p(7) p(8) p(9) p(4) p(5) p(6) p(7) p(8) p(4) p(5) p(6) p(7) p(8) p(9) p(4) p(5) p(6) p(7) p(9) p(4) p(5) p(6) p(8) p(9) p(4) p(5) p(7) p(8) p(4) p(5) p(7) p(8) p(9) SAT clingo-5.2.2/app/clingo/tests/lua/000077500000000000000000000000001320011352300167375ustar00rootroot00000000000000clingo-5.2.2/app/clingo/tests/lua/assumptions1.lp000066400000000000000000000002261320011352300217420ustar00rootroot00000000000000#script (lua) function main(prg) prg:ground({{"base", {}}}) prg:solve{assumptions={{clingo.Function("a"), true}}} end #end. { a }. b :- a. clingo-5.2.2/app/clingo/tests/lua/assumptions1.sol000066400000000000000000000000201320011352300221140ustar00rootroot00000000000000Step: 1 a b SAT clingo-5.2.2/app/clingo/tests/lua/assumptions2.lp000066400000000000000000000002261320011352300217430ustar00rootroot00000000000000#script (lua) function main(prg) prg:ground({{"base", {}}}) prg:solve{assumptions={{clingo.Function("b"), true}}} end #end. { a }. b :- a. clingo-5.2.2/app/clingo/tests/lua/assumptions2.sol000066400000000000000000000000201320011352300221150ustar00rootroot00000000000000Step: 1 a b SAT clingo-5.2.2/app/clingo/tests/lua/assumptions3.lp000066400000000000000000000004671320011352300217530ustar00rootroot00000000000000#script (lua) function main(prg) prg:ground({{"base", {}}}) prg:solve{assumptions={{clingo.Function("a"), true}, {clingo.Function("b"), false}, {clingo.Function("d"), true}}} prg:solve{assumptions={{clingo.Function("a"), false}, {clingo.Function("c"), true}}} end #end. #external d. { a; b; c }. clingo-5.2.2/app/clingo/tests/lua/assumptions3.sol000066400000000000000000000000321320011352300221210ustar00rootroot00000000000000Step: 1 Step: 2 b c c SAT clingo-5.2.2/app/clingo/tests/lua/assumptions4.lp000066400000000000000000000007571320011352300217560ustar00rootroot00000000000000#script (lua) function on_model(m) return true end function on_finish(ret) end function main(prg) local assumptions = {{clingo.Function("a"), true}} prg:ground({{"base", {}}}) prg:solve{on_model=on_model, assumptions=assumptions} prg:solve{on_model=on_model, assumptions=assumptions} local it = prg:solve{assumptions=assumptions, yield=true} local ret = pcall(function() for m in it:iter() do end end) it:close() end #end. { a }. b :- a. clingo-5.2.2/app/clingo/tests/lua/assumptions4.sol000066400000000000000000000000501320011352300221220ustar00rootroot00000000000000Step: 1 a b Step: 2 a b Step: 3 a b SAT clingo-5.2.2/app/clingo/tests/lua/blocksworld1.lp000066400000000000000000000161121320011352300217030ustar00rootroot00000000000000% show instances of selected predicates only #show. % output stack representation #show order/4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for generating states providing relative block positions, using % % - parameter k for block number % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program state(k,t). % a block's scope includes the table (labeled 0) and blocks with smaller numbers scope(k,0,t). scope(k,I,t) :- scope(I,0,t), I < k. % order(1,k,I,t) provides the closest block I in scope above k, if any at time t #count{ I : order(1,k,I,t) : scope(k,I,t), 0 < I } 1. % order(-1,k,I,t) provides the closest block/table I in scope below k at time t 1 #count{ I : order(-1,k,I,t) : scope(k,I,t) } 1. % trace order/4 to derive transitive closure of objects in scope above/below k trans(D,k,I,t) :- order(D,k,I,t). trans(D,k,I,t) :- trans(D,k,J,t), order(D,J,I,t). trans(D,k,J,t) :- trans(D,k,I,t), order(-D,J,I,t), scope(k,J,t). % state constraint that the table is transitively below block k (redundant) :- not trans(-1,k,0,t). % state constraint propagating immediate above/below relationships :- order(-1,k,I,t), order(1,k,J,t), not order(-1,J,I,t), not order(1,I,J,t). % state constraint aligning immediate and transitive above/below relationships :- order(-D,k,J,t), order(D,J,I,t), not trans(D,k,I,t), 0 < I. % D=-1 redundant % state constraint directing transitive above/below relationships on convergence :- order(D,k,I,t), order(D,J,I,t), not trans(-D,k,J,t), scope(k,J,t), 0 < I. % rules below are volatile with life span 1 % #program volatile(k,t). #external scope(k,0,t+1). % goal state conditions :- goal_above(k,I), not trans(-1,k,I,t), not scope(k,0,t+1). :- goal_below(k,I), not trans(1,k,I,t), not scope(k,0,t+1). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for generating moves having a block as object and target, using % % - parameter k for block number % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program move(k,t). % external atoms indicating involvement of blocks with greater numbers in move #external change(-1,k,I,t) : scope(I,0,t), I <= k. #external change( 1,k,I,t) : scope(I,0,t-1), I <= k. #external change(-1,k,t). #external change( 1,k,t). % output object and target block of move #show object(k,t) : object(k,t). #show target(k,t) : target(k,t). % propagate role as move object (via D=1) or target (via D=-1) to smaller block change(1,k-1,I,t) :- order(1,k,I,t), scope(I,0,t-1), not order(1,k,I,t-1). change(D,k-1,I,t) :- order(D,k,I,t-(D+|D|)/2), scope(k,0,t-1), 0 < I, not order(D,k,I,t+(D-|D|)/2). change(D,k-1,I,t) :- change(D,k,I,t), I < k. % , scope(I,0,t-(D+|D|)/2). % combine possibilities how move affects block as object (D=1) or target (D=-1) affect(-D,k,t) :- order(D,k,I,t+(D-|D|)/2), scope(I,0,t-1) : D == 1; not order(D,k,I,t-(D+|D|)/2). affect( D,k,t) :- change(D,k,k,t). % , scope(k,0,t-(D+|D|)/2). % propagate existence of some move object or target to smaller blocks and table change(D,k-1,t) :- affect(D,k,t). change(D,k-1,t) :- change(D,k,t). % derive moved object and corresponding target object(k,t) :- affect(1,k,t). target(k,t) :- affect(-1,k,t), not change(-1,k,t). % moved object must be unique :- object(k,t), change(1,k,t). % moved object must be free :- object(k,t), order(1,k,_,t-1). :- object(I,t), order(-1,k,I,t-1). % moved object must not go under (unmoved) pre-existing block :- object(k,t), order(1,k,I,t), scope(I,0,t-1). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for deriving target table from move without target block, using % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program table(t). % external atoms indicating involvement of blocks with greater numbers in move #external change(-1,0,t). #external change( 1,0,t). % output target table of move #show target(0,t) : target(0,t). % derive table as target of move target(0,t) :- change(1,0,t), not change(-1,0,t). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for establishing consistent initial position for a block, using % % - parameter k for block number % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program init(k,t). % no appearance under unmoved pre-existing block :- order(1,k,I,t), scope(I,0,t-1), not object(I,t). % initial state conditions :- init_above(k,I), not trans(-1,k,I,t). :- init_below(k,I), not trans(1,k,I,t). % clingo-4-banane clingo-4-blocksworld.lp clingo-4-main.lp 0 #script (lua) function main(prg) parts = {} parts[#parts+1] = {"init", {1, 0}} parts[#parts+1] = {"state", {1, 0}} prg:cleanup() prg:ground(parts) prg:solve() parts = {} parts[#parts+1] = {"base_2", {}} parts[#parts+1] = {"init", {2,0}} parts[#parts+1] = {"state", {2,0}} for i=1,2 do parts[#parts+1] = {"table", {i}} for j=1,2 do parts[#parts+1] = {"state", {j,i}} parts[#parts+1] = {"move", {j,i}} end end prg:cleanup() prg:ground(parts) prg:solve() parts = {} parts[#parts+1] = {"base_3", {}} parts[#parts+1] = {"init", {3,0}} parts[#parts+1] = {"state", {3,0}} for i=1,3 do parts[#parts+1] = {"state", {3,i}} parts[#parts+1] = {"move", {3,i}} end for j=1,2 do parts[#parts+1] = {"state", {j,3}} parts[#parts+1] = {"move", {j,3}} end parts[#parts+1] = {"table", {3}} prg:cleanup() prg:ground(parts) prg:solve() parts = {} parts[#parts+1] = {"base_4", {}} parts[#parts+1] = {"init", {4,0}} parts[#parts+1] = {"state", {4,0}} for i=1, 4 do parts[#parts+1] = {"state", {4,i}} parts[#parts+1] = {"move", {4,i}} end for j = 1, 3 do parts[#parts+1] = {"state", {j,4}} parts[#parts+1] = {"move", {j,4}} end parts[#parts+1] = {"table", {4}} prg:cleanup() prg:ground(parts) prg:solve() parts = {} parts[#parts+1] = {"base_5", {}} parts[#parts+1] = {"init", {5,1}} for i=1, 7 do parts[#parts+1] = {"state", {5,i}} parts[#parts+1] = {"move", {5,i}} end for i=5, 7 do parts[#parts+1] = {"table", {i}} for j=1, 4 do parts[#parts+1] = {"state", {j,i}} parts[#parts+1] = {"move", {j,i}} end end prg:cleanup() prg:ground(parts) prg:solve() end #end. #program base_2. init_above(2,1). goal_below(2,1). #program base_3. init_above(3,2). goal_below(3,1). #program base_4. init_above(4,2). init_below(4,3). goal_above(4,3). goal_below(4,1). #program base_5. init_above(5,1). init_below(5,3). goal_above(5,2). clingo-5.2.2/app/clingo/tests/lua/blocksworld1.sol000066400000000000000000000056041320011352300220710ustar00rootroot00000000000000Step: 1 order(-1,1,0,0) Step: 2 object(1,2) object(2,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,2,0,1) order(-1,2,0,2) order(-1,2,1,0) order(1,2,1,2) target(0,1) target(2,2) Step: 3 object(1,3) object(2,2) object(3,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,2,0,2) order(-1,2,0,3) order(-1,2,1,0) order(-1,2,1,1) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,2,0) order(1,2,1,3) order(1,3,2,2) order(1,3,2,3) target(0,1) target(2,3) target(3,2) Step: 4 object(1,4) object(2,3) object(3,1) object(4,2) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,2,0,3) order(-1,2,0,4) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,2,0) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,3,2) order(-1,4,3,3) order(-1,4,3,4) order(1,2,1,4) order(1,3,2,3) order(1,3,2,4) order(1,4,2,3) order(1,4,2,4) order(1,4,3,0) target(0,1) target(2,4) target(3,2) target(4,3) Step: 5 object(1,6) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,7) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,0,6) order(-1,5,1,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,6) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,3,1) target(0,2) target(0,3) target(1,7) target(2,6) target(3,4) target(4,5) target(5,1) object(1,7) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,6) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,2,6) order(-1,5,2,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,1,7) order(1,5,3,1) target(0,2) target(0,3) target(2,6) target(3,4) target(4,5) target(5,1) target(5,7) SAT clingo-5.2.2/app/clingo/tests/lua/check-lua.lp000066400000000000000000000021271320011352300211320ustar00rootroot00000000000000#script (lua) require("clingo") Propagator = { } Propagator.__index = Propagator function Propagator.new() local self = setmetatable({}, Propagator) self.lits = {} return self end function Propagator:init(init) for atom in init.symbolic_atoms:by_signature("p", 1) do local sym = atom.symbol self.lits[#self.lits+1] = init:solver_literal(atom.literal) end assert(init.check_mode == clingo.PropagatorCheckMode.Total) assert(init.check_mode ~= clingo.PropagatorCheckMode.Fixpoint) assert(init.check_mode ~= clingo.PropagatorCheckMode.Off) init.check_mode = clingo.PropagatorCheckMode.Fixpoint assert(init.check_mode == clingo.PropagatorCheckMode.Fixpoint) end function Propagator:check(ctl) -- assert(not ctl.assignment.is_total) for _, lit in ipairs(self.lits) do if ctl.assignment:value(lit) == nil then ctl:add_clause{{lit}} break end end end function main(prg) local p = Propagator.new() prg:register_propagator(p) prg:ground({{"base", {}}}) prg:solve() end #end. { p(1..10) }. clingo-5.2.2/app/clingo/tests/lua/check-lua.sol000066400000000000000000000000771320011352300213160ustar00rootroot00000000000000Step: 1 p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9) SAT clingo-5.2.2/app/clingo/tests/lua/conformant1.lp000066400000000000000000000313511320011352300215260ustar00rootroot00000000000000#script (lua) function main(prg) local step = 0 local check = false while true do parts = {} if step > 0 then parts[#parts+1] = {"step", {step}} else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"state", {step}} if check then parts[#parts+1] = {"check", {step}} end prg:release_external(clingo.Function("vol", {step-1})) prg:cleanup() prg:ground(parts) prg:assign_external(clingo.Function("vol", {step}), true) local ret = prg:solve() if ret.satisfiable then if not check and prg:get_const("nocheck") == nil then check = true parts = {} parts[#parts+1] = {"check", {step}} prg:cleanup() prg:ground(parts) ret = prg:solve() if ret.satisfiable then break end else break end end step = step+1 end end #end. #program warnings. % silence warnings goal_or(0,(0;neg(0)),0) :- #false. #program base. lit(F) :- fluent(F). lit(neg(F)) :- fluent(F). complement(F,F,neg(F)) :- fluent(F). complement(F,neg(F)) :- fluent(F). complement(neg(F),F) :- fluent(F). fluent(F,F) :- fluent(F). fluent(neg(F),F) :- fluent(F). contradict(F) :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2), #false : condition(A,M,N1), condition(A,L,N2), complement(L,M). { holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M). holds(F,0) :- initially(L), complement(F,L,M). holds_oneof(N,B) :- initially_oneof(N,_,B); not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M); holds(F,0) : initially_oneof(N,L,B), complement(F,L,M). :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1. % just bizarre! :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M). :- holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M). #program step(t). 1 { occurs(A,t) : action(A) } 1. :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M). :- occurs(A,t), executable(A,M), holds(F,t-1), complement(F,L,M). holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N). holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t). :- contradict(F), complement(F,L,M), holds((L),t), holds((M),t). caused(L,t) :- occurs(A,t), effect(A,L,N), not holds(F',t-1) : condition(A,M',N), complement(F',L',M'); holds(F',t-1) : condition(A,L',N), complement(F',L',M'). holds(F,t) :- caused(L,t), complement(F,L,M). holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t). :- caused((L),t), caused((M),t), contradict(F), complement(F,L,M). #program state(t). #external vol(t). :- goal_or(N,_,_); not holds(F,t) : goal_or(N,L,_), complement(F,L,M); holds(F,t) : goal_or(N,M,_), complement(F,L,M); vol(t). :- goal(L), not holds(F,t), complement(F,L,M), vol(t). :- goal(M), holds(F,t), complement(F,L,M), vol(t). #program check(t). %%%%%%% base alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L), not initially(M), vol(t). alt_holds(L,0,t) :- initially(L), vol(t). pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B), alt_holds(L,0,t) : initially_oneof(N,L,B). not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t). bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }. bottom(t) :- vol(t), initially_oneof(N,_,_), not_holds_oneof(N,B,t) : initially_oneof(N,_,B). bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t). %%%%%%% transition not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t). not_caused(L,T,t) :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t). alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t). alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t). %%%%%%% state not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t). pos_executable(T,t) :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t). pos_goal_or(N,t) :- goal_or(N,L,B), alt_holds(L,t,t), vol(t). pos_goal_or(N,t) :- goal_or(N,L,B), goal(L), vol(t). bottom(t) :- pos_goal_or(N,t) : goal_or(N,_,_); alt_holds(L,t,t) : goal(L); pos_executable(R,t) : R = 1..t; not_contradict(F,S,t) : contradict(F), S = 1..t; vol(t). %%%%%%% saturation alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L), not initially(M), vol(t). :- not bottom(t), vol(t). #show occurs/2. #program base. fluent(cpa_at(cpa_f1, cpa_p1)). fluent(cpa_inside(cpa_e1)). fluent(cpa_at(cpa_f1, cpa_p0)). fluent(cpa_have(cpa_c0)). fluent(cpa_have(cpa_c1)). fluent(cpa_at(cpa_f0, cpa_p1)). fluent(cpa_inside(cpa_e0)). fluent(cpa_at(cpa_f0, cpa_p0)). fluent(cpa_in(cpa_e0, cpa_f0)). fluent(cpa_in(cpa_e0, cpa_f1)). fluent(cpa_in(cpa_e1, cpa_f0)). fluent(cpa_in(cpa_e1, cpa_f1)). fluent(cpa_coin_at(cpa_c0, cpa_f1, cpa_p0)). fluent(cpa_coin_at(cpa_c0, cpa_f1, cpa_p1)). fluent(cpa_coin_at(cpa_c1, cpa_f1, cpa_p0)). fluent(cpa_coin_at(cpa_c1, cpa_f1, cpa_p1)). %% actions ------ action(cpa_collect(cpa_c0, cpa_f0, cpa_p0)). action(cpa_collect(cpa_c0, cpa_f0, cpa_p1)). action(cpa_collect(cpa_c0, cpa_f1, cpa_p0)). action(cpa_collect(cpa_c0, cpa_f1, cpa_p1)). action(cpa_collect(cpa_c1, cpa_f0, cpa_p0)). action(cpa_collect(cpa_c1, cpa_f0, cpa_p1)). action(cpa_collect(cpa_c1, cpa_f1, cpa_p0)). action(cpa_collect(cpa_c1, cpa_f1, cpa_p1)). action(cpa_go_down(cpa_e0, cpa_f1, cpa_f0)). action(cpa_go_down(cpa_e1, cpa_f1, cpa_f0)). action(cpa_go_up(cpa_e0, cpa_f0, cpa_f1)). action(cpa_go_up(cpa_e1, cpa_f0, cpa_f1)). action(cpa_move_left(cpa_f0, cpa_p1, cpa_p0)). action(cpa_move_left(cpa_f1, cpa_p1, cpa_p0)). action(cpa_move_right(cpa_f0, cpa_p0, cpa_p1)). action(cpa_move_right(cpa_f1, cpa_p0, cpa_p1)). action(cpa_step_in(cpa_e0, cpa_f0, cpa_p0)). action(cpa_step_in(cpa_e0, cpa_f1, cpa_p0)). action(cpa_step_in(cpa_e1, cpa_f0, cpa_p1)). action(cpa_step_in(cpa_e1, cpa_f1, cpa_p1)). action(cpa_step_out(cpa_e0, cpa_f0, cpa_p0)). action(cpa_step_out(cpa_e0, cpa_f1, cpa_p0)). action(cpa_step_out(cpa_e1, cpa_f0, cpa_p1)). action(cpa_step_out(cpa_e1, cpa_f1, cpa_p1)). %% executable ------ executable(cpa_collect(cpa_c0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)). executable(cpa_collect(cpa_c0, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)). executable(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)). executable(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)). executable(cpa_collect(cpa_c1, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)). executable(cpa_collect(cpa_c1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)). executable(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)). executable(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)). executable(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),cpa_at(cpa_f0, cpa_p1)). executable(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),cpa_at(cpa_f1, cpa_p1)). executable(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),cpa_at(cpa_f0, cpa_p0)). executable(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),cpa_at(cpa_f1, cpa_p0)). executable(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)). executable(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)). executable(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)). executable(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)). executable(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_inside(cpa_e0)). executable(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_inside(cpa_e0)). executable(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_inside(cpa_e1)). executable(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_inside(cpa_e1)). %% effects ------ effect(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_have(cpa_c0),1). effect(cpa_collect(cpa_c0, cpa_f1, cpa_p0),neg(cpa_coin_at(cpa_c0, cpa_f1, cpa_p0)),1). condition(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_coin_at(cpa_c0, cpa_f1, cpa_p0),1). effect(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_have(cpa_c0),1). effect(cpa_collect(cpa_c0, cpa_f1, cpa_p1),neg(cpa_coin_at(cpa_c0, cpa_f1, cpa_p1)),1). condition(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_coin_at(cpa_c0, cpa_f1, cpa_p1),1). effect(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_have(cpa_c1),1). effect(cpa_collect(cpa_c1, cpa_f1, cpa_p0),neg(cpa_coin_at(cpa_c1, cpa_f1, cpa_p0)),1). condition(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_coin_at(cpa_c1, cpa_f1, cpa_p0),1). effect(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_have(cpa_c1),1). effect(cpa_collect(cpa_c1, cpa_f1, cpa_p1),neg(cpa_coin_at(cpa_c1, cpa_f1, cpa_p1)),1). condition(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_coin_at(cpa_c1, cpa_f1, cpa_p1),1). effect(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),cpa_in(cpa_e0, cpa_f0),1). effect(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),neg(cpa_in(cpa_e0, cpa_f1)),1). condition(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),cpa_in(cpa_e0, cpa_f1),1). effect(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),cpa_in(cpa_e1, cpa_f0),1). effect(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),neg(cpa_in(cpa_e1, cpa_f1)),1). condition(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),cpa_in(cpa_e1, cpa_f1),1). effect(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),cpa_in(cpa_e0, cpa_f1),1). effect(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),neg(cpa_in(cpa_e0, cpa_f0)),1). condition(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),cpa_in(cpa_e0, cpa_f0),1). effect(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),cpa_in(cpa_e1, cpa_f1),1). effect(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),neg(cpa_in(cpa_e1, cpa_f0)),1). condition(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),cpa_in(cpa_e1, cpa_f0),1). effect(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),neg(cpa_at(cpa_f0, cpa_p1)),1). effect(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),cpa_at(cpa_f0, cpa_p0),1). effect(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),neg(cpa_at(cpa_f1, cpa_p1)),1). effect(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),cpa_at(cpa_f1, cpa_p0),1). effect(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),neg(cpa_at(cpa_f0, cpa_p0)),1). effect(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),cpa_at(cpa_f0, cpa_p1),1). effect(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),neg(cpa_at(cpa_f1, cpa_p0)),1). effect(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),cpa_at(cpa_f1, cpa_p1),1). effect(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_inside(cpa_e0),1). effect(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),neg(cpa_at(cpa_f0, cpa_p0)),1). condition(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_in(cpa_e0, cpa_f0),1). effect(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_inside(cpa_e0),1). effect(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),neg(cpa_at(cpa_f1, cpa_p0)),1). condition(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_in(cpa_e0, cpa_f1),1). effect(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_inside(cpa_e1),1). effect(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),neg(cpa_at(cpa_f0, cpa_p1)),1). condition(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_in(cpa_e1, cpa_f0),1). effect(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_inside(cpa_e1),1). effect(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),neg(cpa_at(cpa_f1, cpa_p1)),1). condition(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_in(cpa_e1, cpa_f1),1). effect(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0),1). effect(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),neg(cpa_inside(cpa_e0)),1). condition(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_in(cpa_e0, cpa_f0),1). effect(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0),1). effect(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),neg(cpa_inside(cpa_e0)),1). condition(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_in(cpa_e0, cpa_f1),1). effect(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1),1). effect(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),neg(cpa_inside(cpa_e1)),1). condition(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_in(cpa_e1, cpa_f0),1). effect(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1),1). effect(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),neg(cpa_inside(cpa_e1)),1). condition(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_in(cpa_e1, cpa_f1),1). %% initial state ------ initially(cpa_at(cpa_f0, cpa_p0)). initially(neg(cpa_at(cpa_f0, cpa_p1))). initially(neg(cpa_at(cpa_f1, cpa_p0))). initially(neg(cpa_at(cpa_f1, cpa_p1))). initially(neg(cpa_inside(cpa_e0))). initially(neg(cpa_inside(cpa_e1))). initially(neg(cpa_have(cpa_c0))). initially(neg(cpa_have(cpa_c1))). initially_oneof(1,cpa_in(cpa_e0, cpa_f0),1). initially_oneof(1,cpa_in(cpa_e0, cpa_f1),2). initially_oneof(2,cpa_in(cpa_e1, cpa_f0),1). initially_oneof(2,cpa_in(cpa_e1, cpa_f1),2). initially_oneof(3,cpa_coin_at(cpa_c0, cpa_f1, cpa_p0),1). initially_oneof(3,cpa_coin_at(cpa_c1, cpa_f1, cpa_p0),1). initially_oneof(3,cpa_coin_at(cpa_c0, cpa_f1, cpa_p1),2). initially_oneof(3,cpa_coin_at(cpa_c1, cpa_f1, cpa_p1),2). %% goal state ---------- goal(cpa_have(cpa_c0)). goal(cpa_have(cpa_c1)). clingo-5.2.2/app/clingo/tests/lua/conformant1.sol000066400000000000000000000326121320011352300217110ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),4) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),4) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3) Step: 7 Step: 8 Step: 9 Step: 10 Step: 11 occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4) SAT clingo-5.2.2/app/clingo/tests/lua/conformant2.lp000066400000000000000000000147461320011352300215400ustar00rootroot00000000000000#script (lua) function main(prg) local step = 0 local check = false while true do parts = {} if step > 0 then parts[#parts+1] = {"step", {step}} else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"state", {step}} if check then parts[#parts+1] = {"check", {step}} end prg:release_external(clingo.Function("vol", {step-1})) prg:cleanup() prg:ground(parts) prg:assign_external(clingo.Function("vol", {step}), true) local ret = prg:solve() if ret.satisfiable then if not check and prg:get_const("nocheck") == nil then check = true parts = {} parts[#parts+1] = {"check", {step}} prg:cleanup() prg:ground(parts) ret = prg:solve() if ret.satisfiable then break end else break end end step = step+1 end end #end. #program warnings. % silence warnings goal_or(0,(0;neg(0)),0) :- #false. #program base. lit(F) :- fluent(F). lit(neg(F)) :- fluent(F). complement(F,F,neg(F)) :- fluent(F). complement(F,neg(F)) :- fluent(F). complement(neg(F),F) :- fluent(F). fluent(F,F) :- fluent(F). fluent(neg(F),F) :- fluent(F). contradict(F) :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2), #false : condition(A,M,N1), condition(A,L,N2), complement(L,M). { holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M). holds(F,0) :- initially(L), complement(F,L,M). holds_oneof(N,B) :- initially_oneof(N,_,B); not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M); holds(F,0) : initially_oneof(N,L,B), complement(F,L,M). :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1. % just bizarre! :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M). :- holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M). #program step(t). 1 { occurs(A,t) : action(A) } 1. :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M). :- occurs(A,t), executable(A,M), holds(F,t-1), complement(F,L,M). holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N). holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t). :- contradict(F), complement(F,L,M), holds((L),t), holds((M),t). caused(L,t) :- occurs(A,t), effect(A,L,N), not holds(F',t-1) : condition(A,M',N), complement(F',L',M'); holds(F',t-1) : condition(A,L',N), complement(F',L',M'). holds(F,t) :- caused(L,t), complement(F,L,M). holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t). :- caused((L),t), caused((M),t), contradict(F), complement(F,L,M). #program state(t). #external vol(t). :- goal_or(N,_,_); not holds(F,t) : goal_or(N,L,_), complement(F,L,M); holds(F,t) : goal_or(N,M,_), complement(F,L,M); vol(t). :- goal(L), not holds(F,t), complement(F,L,M), vol(t). :- goal(M), holds(F,t), complement(F,L,M), vol(t). #program check(t). %%%%%%% base alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L), not initially(M), vol(t). alt_holds(L,0,t) :- initially(L), vol(t). pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B), alt_holds(L,0,t) : initially_oneof(N,L,B). not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t). bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }. bottom(t) :- vol(t), initially_oneof(N,_,_), not_holds_oneof(N,B,t) : initially_oneof(N,_,B). bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t). %%%%%%% transition not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t). not_caused(L,T,t) :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t). alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t). alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t). %%%%%%% state not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t). pos_executable(T,t) :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t). pos_goal_or(N,t) :- goal_or(N,L,B), alt_holds(L,t,t), vol(t). pos_goal_or(N,t) :- goal_or(N,L,B), goal(L), vol(t). bottom(t) :- pos_goal_or(N,t) : goal_or(N,_,_); alt_holds(L,t,t) : goal(L); pos_executable(R,t) : R = 1..t; not_contradict(F,S,t) : contradict(F), S = 1..t; vol(t). %%%%%%% saturation alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L), not initially(M), vol(t). :- not bottom(t), vol(t). #show occurs/2. #program base. fluent(cpa_started). fluent(cpa_visited(cpa_n1)). fluent(cpa_visited(cpa_n2)). fluent(cpa_at(cpa_n1)). fluent(cpa_at(cpa_n2)). %% actions ------ action(cpa_start(cpa_n1)). action(cpa_start(cpa_n2)). action(cpa_travel(cpa_n1, cpa_n1)). action(cpa_travel(cpa_n1, cpa_n2)). action(cpa_travel(cpa_n2, cpa_n1)). action(cpa_travel(cpa_n2, cpa_n2)). %% executable ------ executable(cpa_start(cpa_n1),true). executable(cpa_start(cpa_n2),true). executable(cpa_travel(cpa_n1, cpa_n1),cpa_started). executable(cpa_travel(cpa_n1, cpa_n2),cpa_started). executable(cpa_travel(cpa_n2, cpa_n1),cpa_started). executable(cpa_travel(cpa_n2, cpa_n2),cpa_started). %% effects ------ effect(cpa_start(cpa_n1),cpa_started,1). effect(cpa_start(cpa_n1),cpa_visited(cpa_n1),1). condition(cpa_start(cpa_n1),cpa_at(cpa_n1),1). effect(cpa_start(cpa_n2),cpa_started,1). effect(cpa_start(cpa_n2),cpa_visited(cpa_n2),1). condition(cpa_start(cpa_n2),cpa_at(cpa_n2),1). effect(cpa_travel(cpa_n1, cpa_n2),cpa_visited(cpa_n2),1). effect(cpa_travel(cpa_n1, cpa_n2),cpa_at(cpa_n2),1). effect(cpa_travel(cpa_n1, cpa_n2),neg(cpa_at(cpa_n1)),1). condition(cpa_travel(cpa_n1, cpa_n2),cpa_at(cpa_n1),1). effect(cpa_travel(cpa_n2, cpa_n1),cpa_visited(cpa_n1),1). effect(cpa_travel(cpa_n2, cpa_n1),cpa_at(cpa_n1),1). effect(cpa_travel(cpa_n2, cpa_n1),neg(cpa_at(cpa_n2)),1). condition(cpa_travel(cpa_n2, cpa_n1),cpa_at(cpa_n2),1). %% initial state ------ initially(neg(cpa_visited(cpa_n1))). initially(neg(cpa_visited(cpa_n2))). initially(neg(cpa_started)). initially_oneof(1,cpa_at(cpa_n1),1). initially_oneof(1,cpa_at(cpa_n2),2). %% goal state ---------- goal(cpa_visited(cpa_n1)). goal(cpa_visited(cpa_n2)). clingo-5.2.2/app/clingo/tests/lua/conformant2.sol000066400000000000000000000022641320011352300217120ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 occurs(cpa_start(cpa_n1),1) occurs(cpa_travel(cpa_n1,cpa_n2),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n2,cpa_n1),2) Step: 4 Step: 5 Step: 6 occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4) occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4) occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3) occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3) occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4) occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4) occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3) occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3) SAT clingo-5.2.2/app/clingo/tests/lua/conformant3.lp000066400000000000000000000324241320011352300215320ustar00rootroot00000000000000#script (lua) function main(prg) local step = 0 local check = false while true do parts = {} if step > 0 then parts[#parts+1] = {"step", {step}} else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"state", {step}} if check then parts[#parts+1] = {"check", {step}} end prg:release_external(clingo.Function("vol", {step-1})) prg:cleanup() prg:ground(parts) prg:assign_external(clingo.Function("vol", {step}), true) local ret = prg:solve() if ret.satisfiable then if not check and prg:get_const("nocheck") == nil then check = true parts = {} parts[#parts+1] = {"check", {step}} prg:cleanup() prg:ground(parts) ret = prg:solve() if ret.satisfiable then break end else break end end step = step+1 end end #end. #program warnings. % silence warnings goal_or(0,(0;neg(0)),0) :- #false. #program base. lit(F) :- fluent(F). lit(neg(F)) :- fluent(F). complement(F,F,neg(F)) :- fluent(F). complement(F,neg(F)) :- fluent(F). complement(neg(F),F) :- fluent(F). fluent(F,F) :- fluent(F). fluent(neg(F),F) :- fluent(F). contradict(F) :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2), #false : condition(A,M,N1), condition(A,L,N2), complement(L,M). { holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M). holds(F,0) :- initially(L), complement(F,L,M). holds_oneof(N,B) :- initially_oneof(N,_,B); not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M); holds(F,0) : initially_oneof(N,L,B), complement(F,L,M). :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1. % just bizarre! :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M). :- holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M). #program step(t). 1 { occurs(A,t) : action(A) } 1. :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M). :- occurs(A,t), executable(A,M), holds(F,t-1), complement(F,L,M). holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N). holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t). :- contradict(F), complement(F,L,M), holds((L),t), holds((M),t). caused(L,t) :- occurs(A,t), effect(A,L,N), not holds(F',t-1) : condition(A,M',N), complement(F',L',M'); holds(F',t-1) : condition(A,L',N), complement(F',L',M'). holds(F,t) :- caused(L,t), complement(F,L,M). holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t). :- caused((L),t), caused((M),t), contradict(F), complement(F,L,M). #program state(t). #external vol(t). :- goal_or(N,_,_); not holds(F,t) : goal_or(N,L,_), complement(F,L,M); holds(F,t) : goal_or(N,M,_), complement(F,L,M); vol(t). :- goal(L), not holds(F,t), complement(F,L,M), vol(t). :- goal(M), holds(F,t), complement(F,L,M), vol(t). #program check(t). %%%%%%% base alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L), not initially(M), vol(t). alt_holds(L,0,t) :- initially(L), vol(t). pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B), alt_holds(L,0,t) : initially_oneof(N,L,B). not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t). bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }. bottom(t) :- vol(t), initially_oneof(N,_,_), not_holds_oneof(N,B,t) : initially_oneof(N,_,B). bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t). %%%%%%% transition not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t). not_caused(L,T,t) :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t). alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t). alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t). %%%%%%% state not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t). pos_executable(T,t) :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t). pos_goal_or(N,t) :- goal_or(N,L,B), alt_holds(L,t,t), vol(t). pos_goal_or(N,t) :- goal_or(N,L,B), goal(L), vol(t). bottom(t) :- pos_goal_or(N,t) : goal_or(N,_,_); alt_holds(L,t,t) : goal(L); pos_executable(R,t) : R = 1..t; not_contradict(F,S,t) : contradict(F), S = 1..t; vol(t). %%%%%%% saturation alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L), not initially(M), vol(t). :- not bottom(t), vol(t). #show occurs/2. #program base. fluent(cpa_current_stage(cpa_s5)). fluent(cpa_bad(cpa_p2)). fluent(cpa_ok(cpa_p2)). fluent(cpa_current_stage(cpa_s4)). fluent(cpa_bad(cpa_p1)). fluent(cpa_ok(cpa_p1)). fluent(cpa_current_stage(cpa_s3)). fluent(cpa_read(cpa_p2)). fluent(cpa_bad(cpa_p0)). fluent(cpa_ok(cpa_p0)). fluent(cpa_current_stage(cpa_s2)). fluent(cpa_read(cpa_p1)). fluent(cpa_current_stage(cpa_s1)). fluent(cpa_read(cpa_p0)). fluent(cpa_current_stage(cpa_s0)). fluent(cpa_in_channel(cpa_p0)). fluent(cpa_in_channel(cpa_p1)). fluent(cpa_in_channel(cpa_p2)). fluent(cpa_noisy(cpa_p0)). fluent(cpa_noisy(cpa_p1)). fluent(cpa_noisy(cpa_p2)). %% actions ------ action(cpa_certify(cpa_p0)). action(cpa_certify(cpa_p1)). action(cpa_certify(cpa_p2)). action(cpa_reset(cpa_s1)). action(cpa_reset(cpa_s2)). action(cpa_reset(cpa_s3)). action(cpa_reset(cpa_s4)). action(cpa_reset(cpa_s5)). action(cpa_advance(cpa_s0, cpa_s1)). action(cpa_advance(cpa_s1, cpa_s2)). action(cpa_advance(cpa_s2, cpa_s3)). action(cpa_advance(cpa_s3, cpa_s4)). action(cpa_advance(cpa_s4, cpa_s5)). action(cpa_obtain(cpa_p0, cpa_s0)). action(cpa_obtain(cpa_p1, cpa_s1)). action(cpa_obtain(cpa_p2, cpa_s2)). action(cpa_request_copy(cpa_p0, cpa_s0)). action(cpa_request_copy(cpa_p0, cpa_s1)). action(cpa_request_copy(cpa_p0, cpa_s2)). action(cpa_request_copy(cpa_p0, cpa_s3)). action(cpa_request_copy(cpa_p0, cpa_s4)). action(cpa_request_copy(cpa_p0, cpa_s5)). action(cpa_request_copy(cpa_p1, cpa_s0)). action(cpa_request_copy(cpa_p1, cpa_s1)). action(cpa_request_copy(cpa_p1, cpa_s2)). action(cpa_request_copy(cpa_p1, cpa_s3)). action(cpa_request_copy(cpa_p1, cpa_s4)). action(cpa_request_copy(cpa_p1, cpa_s5)). action(cpa_request_copy(cpa_p2, cpa_s0)). action(cpa_request_copy(cpa_p2, cpa_s1)). action(cpa_request_copy(cpa_p2, cpa_s2)). action(cpa_request_copy(cpa_p2, cpa_s3)). action(cpa_request_copy(cpa_p2, cpa_s4)). action(cpa_request_copy(cpa_p2, cpa_s5)). %% executable ------ executable(cpa_certify(cpa_p0),cpa_read(cpa_p0)). executable(cpa_certify(cpa_p1),cpa_read(cpa_p1)). executable(cpa_certify(cpa_p2),cpa_read(cpa_p2)). executable(cpa_reset(cpa_s1),cpa_current_stage(cpa_s1)). executable(cpa_reset(cpa_s2),cpa_current_stage(cpa_s2)). executable(cpa_reset(cpa_s3),cpa_current_stage(cpa_s3)). executable(cpa_reset(cpa_s4),cpa_current_stage(cpa_s4)). executable(cpa_reset(cpa_s5),cpa_current_stage(cpa_s5)). executable(cpa_advance(cpa_s0, cpa_s1),cpa_current_stage(cpa_s0)). executable(cpa_advance(cpa_s1, cpa_s2),cpa_current_stage(cpa_s1)). executable(cpa_advance(cpa_s2, cpa_s3),cpa_current_stage(cpa_s2)). executable(cpa_advance(cpa_s3, cpa_s4),cpa_current_stage(cpa_s3)). executable(cpa_advance(cpa_s4, cpa_s5),cpa_current_stage(cpa_s4)). executable(cpa_obtain(cpa_p0, cpa_s0),cpa_current_stage(cpa_s0)). executable(cpa_obtain(cpa_p1, cpa_s1),cpa_current_stage(cpa_s1)). executable(cpa_obtain(cpa_p2, cpa_s2),cpa_current_stage(cpa_s2)). executable(cpa_request_copy(cpa_p0, cpa_s0),cpa_current_stage(cpa_s0)). executable(cpa_request_copy(cpa_p0, cpa_s1),cpa_current_stage(cpa_s1)). executable(cpa_request_copy(cpa_p0, cpa_s2),cpa_current_stage(cpa_s2)). executable(cpa_request_copy(cpa_p0, cpa_s3),cpa_current_stage(cpa_s3)). executable(cpa_request_copy(cpa_p0, cpa_s4),cpa_current_stage(cpa_s4)). executable(cpa_request_copy(cpa_p0, cpa_s5),cpa_current_stage(cpa_s5)). executable(cpa_request_copy(cpa_p1, cpa_s0),cpa_current_stage(cpa_s0)). executable(cpa_request_copy(cpa_p1, cpa_s1),cpa_current_stage(cpa_s1)). executable(cpa_request_copy(cpa_p1, cpa_s2),cpa_current_stage(cpa_s2)). executable(cpa_request_copy(cpa_p1, cpa_s3),cpa_current_stage(cpa_s3)). executable(cpa_request_copy(cpa_p1, cpa_s4),cpa_current_stage(cpa_s4)). executable(cpa_request_copy(cpa_p1, cpa_s5),cpa_current_stage(cpa_s5)). executable(cpa_request_copy(cpa_p2, cpa_s0),cpa_current_stage(cpa_s0)). executable(cpa_request_copy(cpa_p2, cpa_s1),cpa_current_stage(cpa_s1)). executable(cpa_request_copy(cpa_p2, cpa_s2),cpa_current_stage(cpa_s2)). executable(cpa_request_copy(cpa_p2, cpa_s3),cpa_current_stage(cpa_s3)). executable(cpa_request_copy(cpa_p2, cpa_s4),cpa_current_stage(cpa_s4)). executable(cpa_request_copy(cpa_p2, cpa_s5),cpa_current_stage(cpa_s5)). %% effects ------ effect(cpa_certify(cpa_p0),cpa_bad(cpa_p0),1). condition(cpa_certify(cpa_p0),cpa_noisy(cpa_p0),1). effect(cpa_certify(cpa_p0),cpa_ok(cpa_p0),2). condition(cpa_certify(cpa_p0),neg(cpa_noisy(cpa_p0)),2). effect(cpa_certify(cpa_p1),cpa_bad(cpa_p1),1). condition(cpa_certify(cpa_p1),cpa_noisy(cpa_p1),1). effect(cpa_certify(cpa_p1),cpa_ok(cpa_p1),2). condition(cpa_certify(cpa_p1),neg(cpa_noisy(cpa_p1)),2). effect(cpa_certify(cpa_p2),cpa_bad(cpa_p2),1). condition(cpa_certify(cpa_p2),cpa_noisy(cpa_p2),1). effect(cpa_certify(cpa_p2),cpa_ok(cpa_p2),2). condition(cpa_certify(cpa_p2),neg(cpa_noisy(cpa_p2)),2). effect(cpa_reset(cpa_s1),neg(cpa_current_stage(cpa_s1)),1). effect(cpa_reset(cpa_s1),cpa_current_stage(cpa_s0),1). effect(cpa_reset(cpa_s2),neg(cpa_current_stage(cpa_s2)),1). effect(cpa_reset(cpa_s2),cpa_current_stage(cpa_s0),1). effect(cpa_reset(cpa_s3),neg(cpa_current_stage(cpa_s3)),1). effect(cpa_reset(cpa_s3),cpa_current_stage(cpa_s0),1). effect(cpa_reset(cpa_s4),neg(cpa_current_stage(cpa_s4)),1). effect(cpa_reset(cpa_s4),cpa_current_stage(cpa_s0),1). effect(cpa_reset(cpa_s5),neg(cpa_current_stage(cpa_s5)),1). effect(cpa_reset(cpa_s5),cpa_current_stage(cpa_s0),1). effect(cpa_advance(cpa_s0, cpa_s1),cpa_current_stage(cpa_s1),1). effect(cpa_advance(cpa_s0, cpa_s1),neg(cpa_current_stage(cpa_s0)),1). effect(cpa_advance(cpa_s1, cpa_s2),cpa_current_stage(cpa_s2),1). effect(cpa_advance(cpa_s1, cpa_s2),neg(cpa_current_stage(cpa_s1)),1). effect(cpa_advance(cpa_s2, cpa_s3),cpa_current_stage(cpa_s3),1). effect(cpa_advance(cpa_s2, cpa_s3),neg(cpa_current_stage(cpa_s2)),1). effect(cpa_advance(cpa_s3, cpa_s4),cpa_current_stage(cpa_s4),1). effect(cpa_advance(cpa_s3, cpa_s4),neg(cpa_current_stage(cpa_s3)),1). effect(cpa_advance(cpa_s4, cpa_s5),cpa_current_stage(cpa_s5),1). effect(cpa_advance(cpa_s4, cpa_s5),neg(cpa_current_stage(cpa_s4)),1). effect(cpa_obtain(cpa_p0, cpa_s0),neg(cpa_in_channel(cpa_p0)),1). effect(cpa_obtain(cpa_p0, cpa_s0),cpa_read(cpa_p0),1). condition(cpa_obtain(cpa_p0, cpa_s0),cpa_in_channel(cpa_p0),1). effect(cpa_obtain(cpa_p1, cpa_s1),neg(cpa_in_channel(cpa_p1)),1). effect(cpa_obtain(cpa_p1, cpa_s1),cpa_read(cpa_p1),1). condition(cpa_obtain(cpa_p1, cpa_s1),cpa_in_channel(cpa_p1),1). effect(cpa_obtain(cpa_p2, cpa_s2),neg(cpa_in_channel(cpa_p2)),1). effect(cpa_obtain(cpa_p2, cpa_s2),cpa_read(cpa_p2),1). condition(cpa_obtain(cpa_p2, cpa_s2),cpa_in_channel(cpa_p2),1). effect(cpa_request_copy(cpa_p0, cpa_s0),cpa_in_channel(cpa_p0),1). effect(cpa_request_copy(cpa_p0, cpa_s0),neg(cpa_read(cpa_p0)),1). effect(cpa_request_copy(cpa_p0, cpa_s0),neg(cpa_noisy(cpa_p0)),1). effect(cpa_request_copy(cpa_p0, cpa_s0),neg(cpa_bad(cpa_p0)),1). condition(cpa_request_copy(cpa_p0, cpa_s0),cpa_bad(cpa_p0),1). effect(cpa_request_copy(cpa_p1, cpa_s1),cpa_in_channel(cpa_p1),1). effect(cpa_request_copy(cpa_p1, cpa_s1),neg(cpa_read(cpa_p1)),1). effect(cpa_request_copy(cpa_p1, cpa_s1),neg(cpa_noisy(cpa_p1)),1). effect(cpa_request_copy(cpa_p1, cpa_s1),neg(cpa_bad(cpa_p1)),1). condition(cpa_request_copy(cpa_p1, cpa_s1),cpa_bad(cpa_p1),1). effect(cpa_request_copy(cpa_p2, cpa_s2),cpa_in_channel(cpa_p2),1). effect(cpa_request_copy(cpa_p2, cpa_s2),neg(cpa_read(cpa_p2)),1). effect(cpa_request_copy(cpa_p2, cpa_s2),neg(cpa_noisy(cpa_p2)),1). effect(cpa_request_copy(cpa_p2, cpa_s2),neg(cpa_bad(cpa_p2)),1). condition(cpa_request_copy(cpa_p2, cpa_s2),cpa_bad(cpa_p2),1). %% initial state ------ initially(cpa_current_stage(cpa_s0)). initially(cpa_in_channel(cpa_p0)). initially(cpa_in_channel(cpa_p1)). initially(cpa_in_channel(cpa_p2)). initially(neg(cpa_current_stage(cpa_s1))). initially(neg(cpa_current_stage(cpa_s2))). initially(neg(cpa_current_stage(cpa_s3))). initially(neg(cpa_current_stage(cpa_s4))). initially(neg(cpa_current_stage(cpa_s5))). initially(neg(cpa_read(cpa_p0))). initially(neg(cpa_read(cpa_p1))). initially(neg(cpa_read(cpa_p2))). initially(neg(cpa_bad(cpa_p0))). initially(neg(cpa_bad(cpa_p1))). initially(neg(cpa_bad(cpa_p2))). initially(neg(cpa_ok(cpa_p0))). initially(neg(cpa_ok(cpa_p1))). initially(neg(cpa_ok(cpa_p2))). initially_oneof(1,cpa_noisy(cpa_p0),1). initially_oneof(1,cpa_noisy(cpa_p2),1). initially_oneof(1,cpa_noisy(cpa_p1),1). initially_oneof(1,neg(cpa_noisy(cpa_p0)),2). initially_oneof(1,neg(cpa_noisy(cpa_p2)),2). initially_oneof(1,neg(cpa_noisy(cpa_p1)),2). %% goal state ---------- goal(cpa_ok(cpa_p0)). goal(cpa_ok(cpa_p1)). goal(cpa_ok(cpa_p2)). clingo-5.2.2/app/clingo/tests/lua/conformant3.sol000066400000000000000000003457161320011352300217270ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),6) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),6) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7) occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6) occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7) Step: 10 Step: 11 Step: 12 Step: 13 Step: 14 Step: 15 Step: 16 Step: 17 Step: 18 Step: 19 occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15) SAT clingo-5.2.2/app/clingo/tests/lua/cover-lua.lp000066400000000000000000000052031320011352300211710ustar00rootroot00000000000000#script (lua) clingo = require("clingo") State = { } State.__index = State function State.new() local x = { leaves = {}, last = nil } setmetatable(x, State) return x end function State:fix(k) local leaf = self.leaves[k.number-1] if leaf then return leaf else return {} end end function State:on_model(m) self.last = m:symbols{atoms=true} for key,atom in ipairs(self.last) do if atom.name == "leaf" then local args = atom.arguments self.leaves[args[1]] = args[2] end end end function State:prepare_instance(k) local edges = {} local cover = {} local vertices = {} for key,atom in ipairs(self.last) do if atom.name == "edge" then local args = atom.arguments if args[1].number == k-1 then edges[#edges + 1] = clingo.Tuple{args[2], args[3]} vertices[#vertices + 1] = args[2] vertices[#vertices + 1] = args[3] end end if atom.name == "cover" then cover[#cover + 1] = atom.arguments[2] end end self.edge = function (self) return edges end self.vertex = function (self) return vertices end self.cover = function (self) return cover end end function State:run(prg) local pre = clingo.Control() pre:add("base", {}, "\ edge(a,(b;c)).\n\ edge(b,(c;d)).\n\ edge(d,e).\n\ edge(e,f).\n\ \n\ edge(x,(a;c)). % edge to keep something to solve\n\ \n\ edge(X,Y) :- edge(Y,X).\n\ vertex(X) :- edge(X,Y;Y,X).\n\ \n\ edge(0,X,Y) :- edge(X,Y).\n") pre:add("step", {"k"}, "\ :- not leaf(k-1,@fix(k)).\n\ \n\ 1 { leaf(k,X) : vertex(X) } 1.\n\ cover(k,X) :- edge(k-1,X,Y), leaf(k,Y).\n\ edge(k,X,Y) :- edge(k-1,X,Y), not cover(k,X), not cover(k,Y).\n\ \n\ :- edge(k-1,X,Y), leaf(k,Y), edge(k-1,Y,Z), X < Z.\n\ :- leaf(k,Y), not edge(k-1,_,Y).\n") pre:ground({{"base", {}}}, self) local ret = pre:solve{on_model=function(...) self:on_model(...) end} local k = 0 while ret.satisfiable do k = k + 1 pre:cleanup() pre:ground({{"step", {k}}}, self) ret = pre:solve{on_model=function(...) self:on_model(...) end} end self:prepare_instance(k) prg:add("base", {}, "\ vertex(X) :- X = @vertex().\n\ edge(X,Y) :- (X,Y) = @edge().\n\ cover(X) :- X = @cover().\n\ \n\ { cover(X) : vertex(X) }.\n\ :- edge(X,Y), not cover(X), not cover(Y).\n\ %#minimize { 1,X : cover(X) }.\n\ \n\ #show cover/1.\n") prg:ground({{"base", {}}}, self) prg.configuration.solve.models = 0 prg:solve() end function main(prg) local s = State.new(prg) s:run(prg) end #end. clingo-5.2.2/app/clingo/tests/lua/cover-lua.sol000066400000000000000000000002451320011352300213540ustar00rootroot00000000000000Step: 1 cover(a) cover(b) cover(c) cover(e) cover(a) cover(b) cover(c) cover(e) cover(x) cover(a) cover(b) cover(e) cover(x) cover(b) cover(c) cover(e) cover(x) SAT clingo-5.2.2/app/clingo/tests/lua/csp-shrinking.lp000066400000000000000000000003161320011352300220530ustar00rootroot00000000000000%!clingo scratch/csp-shrinking.lp 0 -q -V0 #script (lua) function main(prg) for i=10,-2,-3 do prg:ground({{"p", {i}}}) prg:solve() end end #end. #program p(k). -k $<= $x $<= k. clingo-5.2.2/app/clingo/tests/lua/csp-shrinking.sol000066400000000000000000000004061320011352300222350ustar00rootroot00000000000000Step: 1 x=-1 x=-10 x=-2 x=-3 x=-4 x=-5 x=-6 x=-7 x=-8 x=-9 x=0 x=1 x=10 x=2 x=3 x=4 x=5 x=6 x=7 x=8 x=9 Step: 2 x=-1 x=-2 x=-3 x=-4 x=-5 x=-6 x=-7 x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7 Step: 3 x=-1 x=-2 x=-3 x=-4 x=0 x=1 x=2 x=3 x=4 Step: 4 x=-1 x=0 x=1 Step: 5 UNSAT clingo-5.2.2/app/clingo/tests/lua/domain.lp000066400000000000000000000020071320011352300205420ustar00rootroot00000000000000p(1). { p(3) }. #external p(1..3). q(X) :- p(X). #script (lua) clingo = require("clingo") function main(prg) prg:ground({{"base", {}}}) print "Solving..." print "Answer: 1" out = "universe(" .. tostring(#prg.symbolic_atoms) .. ")" for x in prg.symbolic_atoms:iter() do out = out .. " domain(" .. tostring(x.symbol) .. "," .. tostring(x.is_fact) .. "," .. tostring(x.is_external) .. ")" end out = out .. " in_domain(p(2)," .. tostring(prg.symbolic_atoms:lookup(clingo.Function("p", {3})) ~= nil) .. ")" out = out .. " in_domain(p(4)," .. tostring(prg.symbolic_atoms:lookup(clingo.Function("p", {4})) ~= nil) .. ")" for x in prg.symbolic_atoms:by_signature("p", 1) do out = out .. " domain_of_p(" .. tostring(x.symbol) .. "," .. tostring(x.is_fact) .. "," .. tostring(x.is_external) .. ")" end for i,x in ipairs(prg.symbolic_atoms.signatures) do out = out .. " sig(" .. x[1] .. "," .. tostring(x[2]) .. ")" end print (out) io.flush() end #end. clingo-5.2.2/app/clingo/tests/lua/domain.sol000066400000000000000000000005041320011352300207240ustar00rootroot00000000000000Step: 1 domain(p(1),true,false) domain(p(2),false,true) domain(p(3),false,false) domain(q(1),true,false) domain(q(2),false,false) domain(q(3),false,false) domain_of_p(p(1),true,false) domain_of_p(p(2),false,true) domain_of_p(p(3),false,false) in_domain(p(2),true) in_domain(p(4),false) sig(p,1) sig(q,1) universe(6) UNKNOWN clingo-5.2.2/app/clingo/tests/lua/externals.lp000066400000000000000000000005451320011352300213050ustar00rootroot00000000000000#script (lua) Function = clingo.Function function main(prg) prg:ground({{"base", {}}}) prg:assign_external(Function("a"), true) prg:solve() prg:assign_external(Function("a"), false) prg:solve() prg:assign_external(Function("a"), nil) prg:solve() prg:release_external(Function("a")) prg:solve() end #end. #external a. clingo-5.2.2/app/clingo/tests/lua/externals.sol000066400000000000000000000000531320011352300214610ustar00rootroot00000000000000Step: 1 a Step: 2 Step: 3 a Step: 4 SAT clingo-5.2.2/app/clingo/tests/lua/iclingo.lp000066400000000000000000000007451320011352300207260ustar00rootroot00000000000000#program step(k). #external vol(k). p(k). :- vol(k), not 5 { p(K) : K <= k }. #script (lua) function main(prg) step = 0 while true do if step > 0 then prg:release_external(clingo.Function("vol", {step-1})) end prg:ground({{"step", {step}}}) prg:assign_external(clingo.Function("vol", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. clingo-5.2.2/app/clingo/tests/lua/iclingo.sol000066400000000000000000000001141320011352300210760ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 p(0) p(1) p(2) p(3) p(4) vol(4) SAT clingo-5.2.2/app/clingo/tests/lua/icolor.lp000066400000000000000000000016711320011352300205700ustar00rootroot00000000000000% clingo-4.3.0 instance.lp color.ilp -c imin=7 0 #include . #program check(k). :- query(0), k == 0. #program step(k). node(X) :- node(X,k). edge(X,Y) :- edge(X,Y,k). color(C) :- color(C,k). new(X,C,k) :- node(X,k), color(C). new(X,C,k) :- node(X), color(C,k). new(X,Y,C,k) :- edge(X,Y,k), color(C). new(X,Y,C,k) :- edge(X,Y), new(X,C,k). new(X,Y,C,k) :- edge(X,Y), node(Y,k), color(C). { assign(X,C) } :- new(X,C,k). assigned(X,C) :- new(X,C,k), assign(X,C). assigned(X,C) :- new(X,C,k), assigned(X,C+1). :- new(X,C,k), assign(X,C-1), assigned(X,C). :- node(X,k), not assigned(X,1). :- new(X,Y,C,k), assign(X,C), assign(Y,C). % , edge(X,Y) #external assigned(X,1) : node(X,k). #external assigned(X,C+1) : new(X,C,k). #show assign/2. % clingo-4 instance.lp color.lp 0 % clingo-4.3.0 instance.lp color.ilp -c imin=7 0 #program base. node(1,1). color(1,2). color(2,3). node(2,4). edge(1,2,5). node(3,6). edge(2,3,6). color(3,7). clingo-5.2.2/app/clingo/tests/lua/icolor.sol000066400000000000000000000000501320011352300207400ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 assign(1,1) SAT clingo-5.2.2/app/clingo/tests/lua/inccsp-onmodel.cmd000066400000000000000000000000111320011352300223260ustar00rootroot00000000000000--outf=3 clingo-5.2.2/app/clingo/tests/lua/inccsp-onmodel.lp000066400000000000000000000012531320011352300222070ustar00rootroot00000000000000#script (lua) function make_on_model() print ("Solving...") counter = 1 return function (m) print ("Answer: " .. tostring(counter)) print (m) counter = counter + 1 end end function main(prg) prg:ground({{"base", {}}, {"check", {0}}}) prg:solve{on_model=make_on_model()} prg:ground({{"check", {1}}}) prg:solve{on_model=make_on_model()} prg:ground({{"check", {2}}}) prg:solve{on_model=make_on_model()} prg:ground({{"check", {3}}}) prg:solve{on_model=make_on_model()} print ("SATISFIABLE") print () end #end. #program base. 1 { p(0..3) } 1. $x $= 1. #program check(k). #show p/1. #show $x : p(k). clingo-5.2.2/app/clingo/tests/lua/inccsp-onmodel.sol000066400000000000000000000002341320011352300223670ustar00rootroot00000000000000Step: 1 p(0) x=1 p(1) p(2) p(3) Step: 2 p(0) x=1 p(1) x=1 p(2) p(3) Step: 3 p(0) x=1 p(1) x=1 p(2) x=1 p(3) Step: 4 p(0) x=1 p(1) x=1 p(2) x=1 p(3) x=1 SAT clingo-5.2.2/app/clingo/tests/lua/inccsp.lp000066400000000000000000000002011320011352300205440ustar00rootroot00000000000000#include . #const imin=4. #program base. 1 { p(0..3) } 1. $x $= 1. #program check(k). #show p/1. #show $x : p(k). clingo-5.2.2/app/clingo/tests/lua/inccsp.sol000066400000000000000000000002341320011352300207340ustar00rootroot00000000000000Step: 1 p(0) x=1 p(1) p(2) p(3) Step: 2 p(0) x=1 p(1) x=1 p(2) p(3) Step: 3 p(0) x=1 p(1) x=1 p(2) x=1 p(3) Step: 4 p(0) x=1 p(1) x=1 p(2) x=1 p(3) x=1 SAT clingo-5.2.2/app/clingo/tests/lua/incshow.lp000066400000000000000000000001661320011352300207510ustar00rootroot00000000000000#include . #const imin=4. #program base. 1 { p(0..3) } 1. #program check(k). #show p/1. #show x : p(k). clingo-5.2.2/app/clingo/tests/lua/incshow.sol000066400000000000000000000002101320011352300211210ustar00rootroot00000000000000Step: 1 p(0) x p(1) p(2) p(3) Step: 2 p(0) x p(1) x p(2) p(3) Step: 3 p(0) x p(1) x p(2) x p(3) Step: 4 p(0) x p(1) x p(2) x p(3) x SAT clingo-5.2.2/app/clingo/tests/lua/infsup.lp000066400000000000000000000002511320011352300205760ustar00rootroot00000000000000#script (lua) clingo = require("clingo") function inf() return clingo.Infimum end function sup() return clingo.Supremum end #end. inf(@inf()). sup(@sup()). clingo-5.2.2/app/clingo/tests/lua/infsup.sol000066400000000000000000000000401320011352300207540ustar00rootroot00000000000000Step: 1 inf(#inf) sup(#sup) SAT clingo-5.2.2/app/clingo/tests/lua/mutex-bug.lp000066400000000000000000000112471320011352300212160ustar00rootroot00000000000000#script (lua) function main(prg) prg:ground({{"base", {}}, {"plan_graph_base", {}}}) for step = 1,3,1 do prg:ground({{"plan_graph_step", {step}}}) prg:solve() end -- Comment line 8 and uncomment line 11 -- prg:solve() end #end. #program plan_graph_base. valid_f(FLUENT, 1) :- init(FLUENT). valid_f1(FLUENT, 1) :- init(FLUENT). #program plan_graph_step(time). %Encoding 1 valid_a(ACT, time) :- action(ACT); valid_f(FLUENT, time) : pre(ACT, FLUENT); not mutex(F1, F2, time) : req_both(ACT, F1, F2). valid_pre(ACT, FLUENT, time) :- valid_a(ACT, time), pre(ACT, FLUENT). valid_add(ACT, FLUENT, time) :- valid_a(ACT, time), addadd(ACT, FLUENT). valid_f(FLUENT, time + 1) :- valid_add(_, FLUENT, time). mutex_actions(A1, A2, time) :- valid_a(A1, time), valid_a(A2, time), conflicting(A1, A2). mutex_a_with_f(A1, P2, time) :- mutex(P1, P2, time), valid_pre(A1, P1, time). mutex_actions(A1, A2, time) :- mutex_a_with_f(A1, P2, time), valid_pre(A2, P2, time). %mutex_actions(A1, A2, time) :- mutex(P1, P2, time), valid_pre(A1, P1, time), valid_pre(A2, P2, time). mutex_a_sym(A1, A2, time; A2, A1, time) :- mutex_actions(A1, A2, time). closes(A2, F1, time) :- valid_a(A2, time), valid_f(F1, time+1); mutex_a_sym(A1, A2, time) : valid_add(A1, F1, time). mutex(F1, F2, time+1) :- F1 < F2, valid_f(F1, time+1), valid_f(F2, time+1); closes(A2, F1, time) : valid_add(A2, F2, time). % Encoding 2: % Identical to encoding 1 except for lines 32 and 33 vs. line 57. % However these should generate identical groundings, but they don't for some reason valid_a1(ACT, time) :- action(ACT); valid_f1(FLUENT, time) : pre(ACT, FLUENT); not mutex1(F1, F2, time) : req_both(ACT, F1, F2). valid_pre1(ACT, FLUENT, time) :- valid_a1(ACT, time), pre(ACT, FLUENT). valid_add1(ACT, FLUENT, time) :- valid_a1(ACT, time), addadd(ACT, FLUENT). valid_f1(FLUENT, time + 1) :- valid_add1(_, FLUENT, time). mutex_actions1(A1, A2, time) :- valid_a1(A1, time), valid_a1(A2, time), conflicting(A1, A2). %mutex_a_with_f1(A1, P2, time) :- mutex1(P1, P2, time), valid_pre1(A1, P1, time). %mutex_actions1(A1, A2, time) :- mutex_a_with_f1(A1, P2, time), valid_pre1(A2, P2, time). mutex_actions1(A1, A2, time) :- mutex1(P1, P2, time), valid_pre1(A1, P1, time), valid_pre1(A2, P2, time). mutex_a_sym1(A1, A2, time; A2, A1, time) :- mutex_actions1(A1, A2, time). closes1(A2, F1, time) :- valid_a1(A2, time), valid_f1(F1, time+1); mutex_a_sym1(A1, A2, time) : valid_add1(A1, F1, time). mutex1(F1, F2, time+1) :- F1 < F2, valid_f1(F1, time+1), valid_f1(F2, time+1); closes1(A2, F1, time) : valid_add1(A2, F2, time). % diff reports if the two encodings are not the same diff(A1, A2, time) :- mutex_actions1(A1, A2, time), not mutex_actions(A1, A2, time). diff(A1, A2, time) :- mutex_actions(A1, A2, time), not mutex_actions1(A1, A2, time). #program base. #show diff/3. preserve_action(preserve(F)) :- fact(F). action(A) :- preserve_action(A). pre(preserve(F), F) :- fact(F). addadd(preserve(F), F) :- fact(F). prepre(A, F) :- pre(A, F), not del(A, F). deldel(A, F) :- del(A, F), not pre(A, F). predel(A, F) :- pre(A, F), del(A, F). addadd(A, F) :- add(A, F), not pre(A, F), not del(A, F). conflicting(A1, A2) :- pre(A1, F), del(A2, F), A1 != A2. req_both(ACT, F1, F2) :- pre(ACT, F1), pre(ACT, F2), F1 < F2. type(object). type(ferry, object). fact(at_ferry(X)) :- type(X, object). fact(at(X, Y)) :- type(X, object), type(Y, object). fact(on(X, Y)) :- type(X, object), type(Y, object). fact(empty_ferry). action(debark(X, Y)) :- type(X, object), type(Y, object), auto__(X), place__(Y). pre(debark(X, Y), on(X, ferry)) :- action(debark(X, Y)). pre(debark(X, Y), at_ferry(Y)) :- action(debark(X, Y)). add(debark(X, Y), at(X, Y)) :- action(debark(X, Y)). add(debark(X, Y), empty_ferry) :- action(debark(X, Y)). del(debark(X, Y), on(X, ferry)) :- action(debark(X, Y)). action(sail(X, Y)) :- type(X, object), type(Y, object), place__(X), place__(Y). pre(sail(X, Y), at_ferry(X)) :- action(sail(X, Y)). add(sail(X, Y), at_ferry(Y)) :- action(sail(X, Y)). del(sail(X, Y), at_ferry(X)) :- action(sail(X, Y)). action(board(X, Y)) :- type(X, object), type(Y, object), place__(Y), auto__(X). pre(board(X, Y), at(X, Y)) :- action(board(X, Y)). pre(board(X, Y), at_ferry(Y)) :- action(board(X, Y)). pre(board(X, Y), empty_ferry) :- action(board(X, Y)). add(board(X, Y), on(X, ferry)) :- action(board(X, Y)). del(board(X, Y), at(X, Y)) :- action(board(X, Y)). del(board(X, Y), empty_ferry) :- action(board(X, Y)). type(c1, object). type(b, object). type(c2, object). type(a, object). place__(a). place__(b). auto__(c1). auto__(c2). init(at(c1, a)). init(at(c2, a)). init(at_ferry(a)). init(empty_ferry). goal(at(c1, b)). goal(at(c2, b)). clingo-5.2.2/app/clingo/tests/lua/mutex-bug.sol000066400000000000000000000000371320011352300213730ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 SAT clingo-5.2.2/app/clingo/tests/lua/observer-replace.lp000066400000000000000000000165161320011352300225450ustar00rootroot00000000000000#script (lua) function table.shallow_copy(t) local t2 = {} for k,v in pairs(t) do t2[k] = v end return t2 end function table.append(t, val) t[#t + 1] = val end function table.get(t, key, def) local val = t[key] if val ~= nil then return val else return def end end function table.sort_unique(t) local set = {} for k, v in ipairs(t) do set[tostring(v)] = v end local ret = {} for k, v in pairs(set) do table.append(ret, v) end table.sort(ret) return ret end function table.map(t, f) for k, v in ipairs(t) do t[k] = f(v) end return t end function string.startswith(str, pre) return string.sub(str, 1, string.len(pre)) == pre end function bool_to_num(var) return var and 1 or 0 end Function = clingo.Function Tuple = clingo.Tuple local Context = { } function Context:__index(key) return Context[key] end function Context.new(reified) local self = setmetatable({}, Context) self.__reified = table.shallow_copy(reified) return self end function Context:get() return self.__reified end local Observer = { } function Observer.new() local self = setmetatable({}, Observer) self.__delayed = {} self.__symbols = {} self.__reified = {} self.__terms = {} self.__elems = {} return self end function Observer:__index(name) f = Observer[name] if f == nil then assert(not string.startswith(name, "_")) return function (...) table.append(self.__delayed, {name, {...}}) end else return f end end function Observer:__map(lit) local sign = false if lit < 0 then sign = true lit = -lit end local ret = table.get(self.__symbols, lit, Function("__aux")) if sign then ret = Function("neg", {ret}) end return ret end function Observer:__map_lits(t) for k, v in ipairs(t) do t[k] = self:__map(v) end return t end function Observer:__map_wlits(t) for k, v in ipairs(t) do t[k] = Tuple({self:__map(v[1]), v[2]}) end return t end function Observer:init_program(incremental) table.append(self.__reified, Function("init_program", {bool_to_num(incremental)})) end function Observer:begin_step() table.append(self.__reified, Function("begin_step", {})) end function Observer:_rule(choice, head, body) head = table.sort_unique(self:__map_lits(head)) body = table.sort_unique(self:__map_lits(body)) table.append(self.__reified, Function("rule", {bool_to_num(choice), Tuple(head), Tuple(body)})) end function Observer:_weight_rule(choice, head, lower_bound, body) head = table.sort_unique(self:__map_lits(head)) body = table.sort_unique(self:__map_wlits(body)) table.append(self.__reified, Function("weight_rule", {bool_to_num(choice), Tuple(head), lower_bound, Tuple(body)})) end function Observer:_minimize(priority, literals) literals = table.sort_unique(self:__map_wlits(literals)) table.append(self.__reified, Function("minimize", {priority, Tuple(literals)})) end function Observer:_project(atoms) atoms = table.sort_unique(self:__map_lits(atoms)) table.append(self.__reified, Function("project", {Tuple(atoms)})) end function Observer:output_atom(symbol, atom) self.__symbols[atom] = symbol table.append(self.__reified, Function("output_atom", {symbol})) end function Observer:_output_term(symbol, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("output_term", {symbol, Tuple(condition)})) end function Observer:_output_csp(symbol, value, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("output_csp", {symbol, value, Tuple(condition)})) end function Observer:_external(atom, value) table.append(self.__reified, Function("external", {self:__map(atom), tostring(value)})) end function Observer:_assume(literals) literals = table.sort_unique(self:__map_lits(literals)) table.append(self.__reified, Function("assume", {Tuple(literals)})) end function Observer:_heuristic(atom, type, bias, priority, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("heuristic", {atom, tostring(type), bias, Tuple(condition)})) end function Observer:_acyc_edge(node_u, node_v, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("acyc_edge", {node_u, node_v, Tuple(condition)})) end function Observer:theory_term_number(term_id, number) self.__terms[term_id] = function() return number end end function Observer:theory_term_string(term_id, name) self.__terms[term_id] = function() return Function(name) end end function Observer:theory_term_compound(term_id, name_id_or_type, arguments) self.__terms[term_id] = function () return Function(self.__terms[name_id_or_type]().name, table.map(arguments, function (i) return self.__terms[i]() end)) end end function Observer:theory_element(element_id, terms, condition) self.__elems[element_id] = function () condition = table.sort_unique(self:__map_lits(condition)) return Function("elem", {Tuple(table.map(terms, function (i) return self.__terms[i]() end)), Tuple(condition)}) end end function Observer:_theory_atom(atom_id_or_zero, term_id, elements) elements = table.sort_unique(table.map(elements, function (e) return self.__elems[e]() end)) self.__symbols[atom_id_or_zero] = Function("theory", {self.__terms[term_id](), Tuple(elements)}); end function Observer:_theory_atom_with_guard(atom_id_or_zero, term_id, elements, operator_id, right_hand_side_id) elements = table.sort_unique(table.map(elements, function (e) return self.__elems[e]() end)) self.__symbols[atom_id_or_zero] = Function("theory", {self.__terms[term_id](), Tuple(elements), self.__terms[operator_id](), self.__terms[right_hand_side_id]()}); end function Observer:end_step() table.append(self.__reified, Function("end_step", {})) end function Observer:finalize() if unpack == nil then unpack = table.unpack end for _, v in ipairs(self.__delayed) do local name, args name, args = v[1], v[2] if string.startswith(name, "theory_atom") then self["_" .. name](unpack(args)) end end for _, v in ipairs(self.__delayed) do local name, args name, args = v[1], v[2] if not string.startswith(name, "theory_atom") then self["_" .. name](unpack(args)) end end return Context.new(self.__reified) end function main(prg) obs = Observer.new() prg:register_observer(obs, true) prg:ground({{"base", {}}}) prg:solve{assumptions={{Function("b"), false}}} ctx = obs:finalize() prg:add("q", {}, "q(@get()).") prg:ground({{"q", {}}}, ctx) prg:solve() print "Solving..." print "Answer: 1" print (table.concat(table.map(ctx:get(), tostring), " ")) io.flush() end #end. $x $= 1. $y $= 2. 1 {a; b}. #minimize {1:a; 2:b}. #project a. #show x : a, b. #external a. #heuristic a : b. [1@2,sign] #edge (a,b) : a, b. #theory t { term { + : 1, binary, left }; &a/0 : term, any; &b/1 : term, {=}, term, any }. a :- &a { 1+2,"test": a, b }. b :- &b(3) { } = 17. clingo-5.2.2/app/clingo/tests/lua/observer-replace.sol000066400000000000000000000007641320011352300227250ustar00rootroot00000000000000Step: 1 acyc_edge(0,1,(a,b)) assume((neg(b),)) begin_step end_step external(a,"False") heuristic(2,"Sign",1,(b,)) init_program(1) minimize(0,((a,1),(b,2))) output_atom(a) output_atom(b) output_csp(x,1,()) output_csp(y,2,()) output_term(x,(__aux,)) project((a,)) rule(0,(),(__aux,neg(__aux))) rule(0,(__aux,),()) rule(0,(__aux,),(a,b)) rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),)) rule(0,(b,),(theory(b(3),(),=,17),)) rule(1,(a,b),(__aux,)) weight_rule(0,(__aux,),1,((a,1),(b,1))) UNKNOWN clingo-5.2.2/app/clingo/tests/lua/observer.cmd000066400000000000000000000000221320011352300212450ustar00rootroot00000000000000--opt-mode=ignore clingo-5.2.2/app/clingo/tests/lua/observer.lp000066400000000000000000000164351320011352300211340ustar00rootroot00000000000000#script (lua) function table.shallow_copy(t) local t2 = {} for k,v in pairs(t) do t2[k] = v end return t2 end function table.append(t, val) t[#t + 1] = val end function table.get(t, key, def) local val = t[key] if val ~= nil then return val else return def end end function table.sort_unique(t) local set = {} for k, v in ipairs(t) do set[tostring(v)] = v end local ret = {} for k, v in pairs(set) do table.append(ret, v) end table.sort(ret) return ret end function table.map(t, f) for k, v in ipairs(t) do t[k] = f(v) end return t end function string.startswith(str, pre) return string.sub(str, 1, string.len(pre)) == pre end function bool_to_num(var) return var and 1 or 0 end Function = clingo.Function Tuple = clingo.Tuple local Context = { } function Context:__index(key) return Context[key] end function Context.new(reified) local self = setmetatable({}, Context) self.__reified = table.shallow_copy(reified) return self end function Context:get() return self.__reified end local Observer = { } Observer.__index = Observer function Observer.new() local self = setmetatable({}, Observer) self.__delayed = {} self.__symbols = {} self.__reified = {} self.__terms = {} self.__elems = {} return self end function Observer:__index(name) f = Observer[name] if f == nil then assert(not string.startswith(name, "_")) return function (...) table.append(self.__delayed, {name, {...}}) end else return f end end function Observer:__map(lit) local sign = false if lit < 0 then sign = true lit = -lit end local ret = table.get(self.__symbols, lit, Function("__aux")) if sign then ret = Function("neg", {ret}) end return ret end function Observer:__map_lits(t) for k, v in ipairs(t) do t[k] = self:__map(v) end return t end function Observer:__map_wlits(t) for k, v in ipairs(t) do t[k] = Tuple({self:__map(v[1]), v[2]}) end return t end function Observer:init_program(incremental) table.append(self.__reified, Function("init_program", {bool_to_num(incremental)})) end function Observer:begin_step() table.append(self.__reified, Function("begin_step", {})) end function Observer:_rule(choice, head, body) head = table.sort_unique(self:__map_lits(head)) body = table.sort_unique(self:__map_lits(body)) table.append(self.__reified, Function("rule", {bool_to_num(choice), Tuple(head), Tuple(body)})) end function Observer:_weight_rule(choice, head, lower_bound, body) head = table.sort_unique(self:__map_lits(head)) body = table.sort_unique(self:__map_wlits(body)) table.append(self.__reified, Function("weight_rule", {bool_to_num(choice), Tuple(head), lower_bound, Tuple(body)})) end function Observer:_minimize(priority, literals) literals = table.sort_unique(self:__map_wlits(literals)) table.append(self.__reified, Function("minimize", {priority, Tuple(literals)})) end function Observer:_project(atoms) atoms = table.sort_unique(self:__map_lits(atoms)) table.append(self.__reified, Function("project", {Tuple(atoms)})) end function Observer:output_atom(symbol, atom) self.__symbols[atom] = symbol table.append(self.__reified, Function("output_atom", {symbol})) end function Observer:_output_term(symbol, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("output_term", {symbol, Tuple(condition)})) end function Observer:_output_csp(symbol, value, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("output_csp", {symbol, value, Tuple(condition)})) end function Observer:_external(atom, value) table.append(self.__reified, Function("external", {self:__map(atom), tostring(value)})) end function Observer:_assume(literals) literals = table.sort_unique(self:__map_lits(literals)) table.append(self.__reified, Function("assume", {Tuple(literals)})) end function Observer:_heuristic(atom, type, bias, priority, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("heuristic", {atom, tostring(type), bias, Tuple(condition)})) end function Observer:_acyc_edge(node_u, node_v, condition) condition = table.sort_unique(self:__map_lits(condition)) table.append(self.__reified, Function("acyc_edge", {node_u, node_v, Tuple(condition)})) end function Observer:theory_term_number(term_id, number) self.__terms[term_id] = function() return number end end function Observer:theory_term_string(term_id, name) self.__terms[term_id] = function() return Function(name) end end function Observer:theory_term_compound(term_id, name_id_or_type, arguments) self.__terms[term_id] = function () return Function(self.__terms[name_id_or_type]().name, table.map(arguments, function (i) return self.__terms[i]() end)) end end function Observer:theory_element(element_id, terms, condition) self.__elems[element_id] = function () condition = table.sort_unique(self:__map_lits(condition)) return Function("elem", {Tuple(table.map(terms, function (i) return self.__terms[i]() end)), Tuple(condition)}) end end function Observer:_theory_atom(atom_id_or_zero, term_id, elements) elements = table.sort_unique(table.map(elements, function (e) return self.__elems[e]() end)) self.__symbols[atom_id_or_zero] = Function("theory", {self.__terms[term_id](), Tuple(elements)}); end function Observer:_theory_atom_with_guard(atom_id_or_zero, term_id, elements, operator_id, right_hand_side_id) elements = table.sort_unique(table.map(elements, function (e) return self.__elems[e]() end)) self.__symbols[atom_id_or_zero] = Function("theory", {self.__terms[term_id](), Tuple(elements), self.__terms[operator_id](), self.__terms[right_hand_side_id]()}); end function Observer:end_step() table.append(self.__reified, Function("end_step", {})) end function Observer:finalize() if unpack == nil then unpack = table.unpack end for _, v in ipairs(self.__delayed) do local name, args name, args = v[1], v[2] if string.startswith(name, "theory_atom") then self["_" .. name](unpack(args)) end end for _, v in ipairs(self.__delayed) do local name, args name, args = v[1], v[2] if not string.startswith(name, "theory_atom") then self["_" .. name](unpack(args)) end end return Context.new(self.__reified) end function main(prg) f = Function("f", {1}) g = Function("g") obs = Observer.new() prg:register_observer(obs) prg:ground({{"base", {}}}) prg:solve{assumptions={{Function("b"), false}}} ctx = obs:finalize() prg:add("q", {}, "q(@get()).") prg:ground({{"q", {}}}, ctx) prg:solve() end #end. $x $= 1. $y $= 2. 1 {a; b}. #minimize {1:a; 2:b}. #project a. #show x : a, b. #external a. #heuristic a : b. [1@2,sign] #edge (a,b) : a, b. #theory t { term { + : 1, binary, left }; &a/0 : term, any; &b/1 : term, {=}, term, any }. a :- &a { 1+2,"test": a, b }. b :- &b(3) { } = 17. clingo-5.2.2/app/clingo/tests/lua/observer.sol000066400000000000000000000106401320011352300213060ustar00rootroot00000000000000Step: 1 a x=1 y=2 a x=1 y=2 Step: 2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 a q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 SAT clingo-5.2.2/app/clingo/tests/lua/parse-term.lp000066400000000000000000000003471320011352300213570ustar00rootroot00000000000000#script (lua) c = clingo.Control() function get() return { clingo.parse_term("1"), clingo.parse_term("p(1+2)"), clingo.parse_term("-p"), clingo.parse_term("-p(1)") } end c:ground({{"base", {}}}) c:solve() #end. p(@get()). clingo-5.2.2/app/clingo/tests/lua/parse-term.sol000066400000000000000000000000501320011352300215300ustar00rootroot00000000000000Step: 1 p(-p(1)) p(-p) p(1) p(p(3)) SAT clingo-5.2.2/app/clingo/tests/lua/project_bug.lp000066400000000000000000000002571320011352300216030ustar00rootroot00000000000000#script (lua) function main(ctl) ctl:ground({{"base",{}}}) ctl:add("rules", {}, "r :- q(_), p.") ctl:ground({{"rules", {}}}) ctl:solve() end #end. p. q(1). clingo-5.2.2/app/clingo/tests/lua/project_bug.sol000066400000000000000000000000251320011352300217560ustar00rootroot00000000000000Step: 1 p q(1) r SAT clingo-5.2.2/app/clingo/tests/lua/propagator.cmd000066400000000000000000000000061320011352300215760ustar00rootroot00000000000000-q1,1 clingo-5.2.2/app/clingo/tests/lua/propagator.lp000066400000000000000000000231711320011352300214560ustar00rootroot00000000000000#script (lua) require("clingo") -- {{{1 Aux function max(a, b) if a < b then return b else return a end end function table.unique(t) local res, n = 1, #t for i = 2, n do if t[i] ~= t[i-1] then res = res + 1 t[res] = t[i] end end for i = res+1, n do t[i] = nil end end function table.copy(t) local u = {} for i, v in pairs(t) do u[i] = v end return u end function table.find(t, k) for _, v in pairs(t) do if v == k then return true end end return false end function table.tostring(t) local r, c = "", false for _, k in ipairs(t) do if c then r = r .. "," else c = true end r = r .. tostring(k) end return r end function table.append(t, v) t[#t+1] = v end function table.setdefault(t, k, d) local x = t[k] if x == nil then x = d t[k] = x end return x end function table.keys(t) local keys = {} for k, _ in pairs(t) do table.append(keys, k) end return keys end -- {{{1 State local State = { } State.__index = State function State.new(pat_len, seq_len) local self = setmetatable({ }, State) self.seq_active = {} self.stack = {} self.trail = {} self.pat = {} self.pat_assigned = 0 self.pat_len = pat_len self.seq_len = seq_len for i = 1, seq_len do self.seq_active[i] = true end return self end -- {{{1 Propagator local Propagator = { } Propagator.__index = Propagator -- {{{2 Initialization function Propagator.new() local self = setmetatable({ }, Propagator) self.__seq_atoms = {} self.__pat_atoms = {} self.__occ_list = {} self.__item_map = {} self.__item_num = 0 self.__pat_len = 0 return self end function Propagator:__map_item(item) local mapped = self.__item_map[item] if mapped == nil then self.__item_num = self.__item_num + 1 mapped = self.__item_num self.__item_map[item] = mapped end return mapped end function Propagator:__add_seq_atom(init, sid, atom) assert(self.__seq_atoms[sid] == nil) self.__seq_atoms[sid] = {init:solver_literal(atom.literal), {}} for _, elem in ipairs(atom.elements) do local index, item = elem.terms[1].number + 1, elem.terms[2] assert(index >= 1) local item = self:__map_item(tostring(item)) self.__seq_atoms[sid][2][index] = item end end function Propagator:__add_pat_atoms(init, atom) for _, elem in ipairs(atom.elements) do local lit = init:solver_literal(elem.condition_id) local index, item = elem.terms[1].number + 1, elem.terms[2] assert(index >= 1) local item = self:__map_item(tostring(item)) local pat = {index, item} local pat_atom = self.__pat_atoms[lit] if pat_atom == nil then init:add_watch(lit) pat_atom = {} self.__pat_atoms[lit] = pat_atom end pat_atom[#pat_atom + 1] = pat self.__pat_len = max(self.__pat_len, index) end end function Propagator:__init_occ_list() for i = 1, self.__item_num do self.__occ_list[#self.__occ_list + 1] = {} end local sid = 1 for _, seq in ipairs(self.__seq_atoms) do local set = table.copy(seq[2]) table.sort(set) table.unique(set) for _, item in ipairs(set) do assert(item ~= nil) table.append(self.__occ_list[item], sid) end sid = sid + 1 end end function Propagator:init(init) for atom in init.theory_atoms do term = atom.term args = term.arguments if term.name == "seq" and #args == 1 then self:__add_seq_atom(init, args[1].number + 1, atom) end if term.name == "pat" and #args == 0 then self:__add_pat_atoms(init, atom) end end self:__init_occ_list() for i = 1, init.number_of_threads do init:set_state(i, State.new(self.__pat_len, #self.__seq_atoms)) end end -- {{{2 Propagation function Propagator:__propagate_sequence_lit(state, control, sid, lit) --print (" propagate_lit: " .. tostring(sid) .. "/" .. tostring(lit)) state.seq_active[sid] = false table.append(state.stack, -sid) if not control.assignment:is_true(lit) then local klaus = {lit} for i = 1, self.__pat_len do local pat = state.pat[i] if pat ~= nil then table.append(klaus, -pat[1]) end end --print (" add_clause: " .. table.tostring(klaus)) return control:add_clause{klaus} and control:propagate() end return true end function Propagator:__propagate_sequence(state, control, sid, lit, items) --print (" propagate sequence: " .. tostring(sid) .. "/" .. tostring(lit) .. "/" .. table.tostring(items)) if state.pat_assigned < self.__pat_len and control.assignment:is_false(lit) then return true end local iid = 1 for i = 1, self.__pat_len do pat = state.pat[i] while true do if iid > #items then return self:__propagate_sequence_lit(state, control, sid, -lit) end iid = iid + 1 if pat == nil or items[iid-1] == pat[2] then break end end end return state.pat_assigned < self.__pat_len or self:__propagate_sequence_lit(state, control, sid, lit) end function Propagator:propagate(control, changes, state) --print ("propagate: " .. table.tostring(changes)) if #state.trail == 0 or state.trail[#state.trail][1] < control.assignment.decision_level then table.append(state.trail, {control.assignment.decision_level, #state.stack + 1}) end for _, lit in ipairs(changes) do for _, pat in ipairs(self.__pat_atoms[lit]) do if state.pat[pat[1]] ~= nil then assert(false) -- this case should not occur if the pattern is generated properly local old = state.pat[pat[1]][1] assert(control.assignment:is_true(old)) if not control:add_clause{{-lit, -old}} or not control:propagate() then return end else table.append(state.stack, pat[1]) state.pat_assigned = state.pat_assigned + 1 state.pat[pat[1]] = {lit, pat[2]} for _, sid in ipairs(self.__occ_list[pat[2]]) do local atom = self.__seq_atoms[sid] if state.seq_active[sid] and not self:__propagate_sequence(state, control, sid, atom[1], atom[2]) then return end end end end end end function Propagator:undo(id, assign, changes, state) --print ("undo: " .. table.tostring(changes)) sid = state.trail[#state.trail][2] for i = sid, #state.stack do psid = state.stack[i] if psid >= 1 then state.pat[psid] = nil state.pat_assigned = state.pat_assigned - 1 else state.seq_active[-psid] = true end state.stack[i] = nil end state.trail[#state.trail] = nil end -- {{{1 Main function main(c) c.configuration.solve.opt_mode = "optN" c:ground({ {"base", {}} }) c:register_propagator(Propagator.new()) -- :- not sup(U), seq(U,_,_), n == 0. if c:get_const("n").number == 0 then local grouped = {} for atom in c.symbolic_atoms:by_signature("seq", 3) do table.append(table.setdefault(grouped, atom.symbol.arguments[1].number, {}), atom.literal) end local keys = table.keys(grouped) table.sort(keys) for _, key in ipairs(keys) do local a = c.backend:add_atom() for _, l in ipairs(grouped[key]) do c.backend:add_rule{{a}, {l}} end c.backend:add_rule{{}, {-c.symbolic_atoms:lookup(clingo.Function("sup", {key})).literal, a}} end end -- :- sup(U), pat(_,I), not seq(U,_,I). local grouped_pat, grouped_seq = {}, {} for atom in c.symbolic_atoms:by_signature("pat", 2) do table.append(table.setdefault(grouped_pat, tostring(atom.symbol.arguments[2]), {}), atom.literal) end for atom in c.symbolic_atoms:by_signature("seq", 3) do local a, b = atom.symbol.arguments[1], atom.symbol.arguments[3] grouped_seq[tostring(a) .. "," .. tostring(b)] = true end local projected_pat, projected_seq = {}, {} local keys = table.keys(grouped_pat) table.sort(keys) for _, key in ipairs(keys) do local a = c.backend:add_atom() for _, l in ipairs(grouped_pat[key]) do c.backend:add_rule{{a}, {l}} end projected_pat[key] = a end for atom in c.symbolic_atoms:by_signature("sup", 1) do for _, key in ipairs(keys) do local a, b = atom.symbol.arguments[1], key if not grouped_seq[tostring(a) .. "," .. tostring(b)] then c.backend:add_rule{{}, {atom.literal, projected_pat[key]}} end end end c:solve() end -- }}}1 #end. % {{{1 ASP #show pat/2. #theory seq { term { }; &seq/1 : term, body; &pat/0 : term, directive }. #const n = 5. 1 { pat(P,I) : seq(_,_,I) } 1 :- P = 0..(n-1). &pat { P,I : pat(P,I) }. sup(U) :- &seq(U) { P,I : seq(U,P,I) }, seq(U,_,_). #maximize { 1,U : sup(U) }. % abaca seq(0,0,a). seq(0,1,b). seq(0,2,a). seq(0,3,c). seq(0,4,a). % abdca seq(1,0,a). seq(1,1,b). seq(1,2,d). seq(1,3,c). seq(1,4,a). % aedca seq(2,0,a). seq(2,1,e). seq(2,2,d). seq(2,3,c). seq(2,4,a). clingo-5.2.2/app/clingo/tests/lua/propagator.sol000066400000000000000000000002351320011352300216340ustar00rootroot00000000000000Step: 1 pat(0,a) pat(1,b) pat(2,a) pat(3,c) pat(4,a) pat(0,a) pat(1,b) pat(2,d) pat(3,c) pat(4,a) pat(0,a) pat(1,e) pat(2,d) pat(3,c) pat(4,a) OPTIMUM FOUND clingo-5.2.2/app/clingo/tests/lua/queens.lp000066400000000000000000000015101320011352300205710ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 stop = 10 while true do if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) end prg:ground({{"cumulative", {step}}}) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if step == stop then break end step = step + 1 end end #end. #program cumulative(k). dim(k). {q(X,k) : dim(X)}. {q(k,Y) : dim(Y), Y 1 then prg:release_external(clingo.Function("volatile", {step-1})) else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. #program base. dim(1..dimension). robot(red). robot(blue). robot(green). robot(yellow). direction(north). direction(east). direction(south). direction(west). % blockages blocked(I,J,D) :- barrier(I,J,D),direction(D),dim(I),dim(J). blocked(1..dimension,1 ,north). blocked( dimension,1..dimension,east ). blocked(1..dimension, dimension,south). blocked( 1,1..dimension,west ). blocked(I+1,J,west ) :- blocked(I,J,east ), dim(I), dim(J), I1. blocked(I,J-1,south) :- blocked(I,J,north), dim(I), dim(J), J>1. % this should simplify sth. dir(west, -1, 0). dir(east, 1, 0). dir(north, 0, -1). dir(south, 0, 1). #program cumulative(t). % which places are reachable by a robot reachable(R, I + DI, J + DJ, D, t) :- not blocked2(I, J, t), dir(D, DI, DJ), go(R, D, t), position(R, I, J, t - 1), dim(I), dim(J). reachable(R, I + DI, J + DJ, D, t) :- not blocked2(I, J, t), reachable(R, I, J, D, t), dir(D, DI, DJ), go(R, D, t), dim(I), dim(J). % no crossing of blockages or robots blocked2(I, J, t) :- blocked(I, J, D), go(R, D, t). blocked2(I - DI, J - DJ, t) :- position(R, I, J, t - 1), selectDir(D, t), dir(D, DI, DJ). % move it (no stopping if there is neither a blockage nor a robot) position(R, I, J, t) :- reachable(R, I, J, D, t), not reachable(R, I + DI, J + DJ, D, t), dir(D, DI, DJ), go(R, D, t). % one has to be moved moved(t) :- reachable(R, I, J, D, t). :- not moved(t). % inertia position(R, I, J, t) :- position(R, I, J, t - 1), not selectRobot(R, t), robot(R), dim(I),dim(J). % plan generator 1 { selectRobot(R, t) : robot(R) } 1. 1 { selectDir(D,t) : direction(D) } 1. go(R, D, t) :- selectRobot(R, t), selectDir(D,t). %#show moved/4. #show go/3. #show position/4. %#show reachable/4. % Authentic board from Ricochet Robots (Rasende Roboter) by Alex Randolph #const dimension=16. #external volatile(t). % --- Uncomment an integrity constraint to pose a query % - numbers indicated minimum number of moves % - sometimes a heuristics was better than another :- instance(1), not position(red, 5,2,t), volatile(t). % red moon: 9, vmtf :- instance(2), not position(red, 15,2,t), volatile(t). % red triangle: 10, ? :- instance(3), not position(green, 2,3,t), volatile(t). % green triangle: 9, berkmin :- instance(4), not position(blue, 12,3,t), volatile(t). % blue star: 8, ? :- instance(5), not position(yellow, 7,4,t), volatile(t). % yellow star: 11, ? :- instance(6), not position(blue, 4,7,t), volatile(t). % blue saturn: 8, ? :- instance(7), not position(green, 14,7,t), volatile(t). % green moon: 3, ? :- instance(8), not position(yellow, 11,8,t), volatile(t). % yellow saturn: 13, vmtf?? :- instance(9), not position(yellow, 5,10,t), volatile(t). % yellow moon: 2, ? :- instance(10), not position(green, 2,11,t), volatile(t). % green star: 11, ? :- instance(11), not position(red, 14,11,t), volatile(t). % red star: 9, ? :- instance(12), not position(green, 11,12,t), volatile(t). % green saturn: 11, ? :- instance(13), not position(yellow,15,13,t), volatile(t). % yellow star: 9, ? :- instance(14), not position(blue, 7,14,t), volatile(t). % blue star: 6, ? :- instance(15), not position(red, 3,15,t), volatile(t). % red saturn: 5, ? :- instance(16), not position(blue, 10,15,t), volatile(t). % blue moon: 12, vsids? %:- not position(red,1,1,t), t==0. %:- not position(blue,1,16,t), t==0. %:- not position(green,16,1,t), t==0. %:- not position(yellow,16,16,t), t==0. %:- not go(red,east,t), t==1. :- not position(blue,1,16,t), t==1. %:- not position(green,16,1,t), t==1. %:- not position(yellow,16,16,t), t==1. %:- not position(red,2,1,t), t==1. %:- not go(red,south,t), t==2. %:- not position(blue,1,16,t), t==2. :- not position(green,16,1,t), t==2. %:- not position(yellow,16,16,t), t==2. %:- not position(red,2,2,t), t==2. %:- not go(red,east,t), t==3. %:- not position(blue,1,16,t), t==3. %:- not position(green,16,1,t), t==3. %:- not position(yellow,16,16,t), t==3. :- not position(red,4,2,t), t==3. %:- not go(red,north,t), t==4. %:- not position(blue,1,16,t), t==4. %:- not position(green,16,1,t), t==4. %:- not position(yellow,16,16,t), t==4. %:- not position(red,4,1,t), t==4. %:- not go(red,west,t), t==5. %:- not position(blue,1,16,t), t==5. %:- not position(green,16,1,t), t==5. %:- not position(yellow,16,16,t), t==5. %:- not position(red,3,1,t), t==5. :- not go(red,south,t), t==6. %:- not position(blue,1,16,t), t==6. %:- not position(green,16,1,t), t==6. %:- not position(yellow,16,16,t), t==6. %:- not position(red,3,15,t), t==6. #program base. instance(15). position(red,1,1,0). position(blue,1,dimension,0). position(green,dimension,1,0). position(yellow,dimension,dimension,0). barrier( 2, 1,east). barrier(10, 1,east). barrier( 4, 2,east). barrier(14, 2,east). barrier( 2, 3,east). barrier( 11,3,east). barrier( 7, 4,east). barrier( 3, 7,east). barrier( 14,7,east). barrier( 7, 8,east). % middle barrier( 10,8,west). % middle barrier( 11,8,east). barrier( 7, 9,east). % middle barrier( 10,9,west). % middle barrier( 4,10,east). barrier( 2,11,east). barrier( 8,11,east). barrier(13,11,east). barrier(11,12,east). barrier(14,13,east). barrier( 6,14,east). barrier(3, 15,east). barrier(10,15,east). barrier(4, 16,east). barrier(12,16,east). barrier( 5, 1,south). barrier(15, 1,south). barrier( 2, 2,south). barrier(12, 3,south). barrier( 7, 4,south). barrier(16, 4,south). barrier( 1, 6,south). barrier( 4, 7,south). barrier( 8, 7,south). % middle barrier( 9, 7,south). % middle barrier(11, 7,south). barrier(14, 7,south). barrier(16, 9,south). barrier( 2,10,south). barrier( 5,10,south). barrier( 8,10,north). % middle barrier( 9,10,north). % middle barrier( 9,10,south). barrier(14,10,south). barrier( 1,12,south). barrier(11,12,south). barrier( 7,13,south). barrier(15,13,south). barrier(10,14,south). barrier( 3,15,south). clingo-5.2.2/app/clingo/tests/lua/robots.sol000066400000000000000000000014101320011352300207620ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 go(red,east,1) go(red,east,3) go(red,north,4) go(red,south,2) go(red,south,6) go(red,west,5) position(blue,1,16,0) position(blue,1,16,1) position(blue,1,16,2) position(blue,1,16,3) position(blue,1,16,4) position(blue,1,16,5) position(blue,1,16,6) position(green,16,1,0) position(green,16,1,1) position(green,16,1,2) position(green,16,1,3) position(green,16,1,4) position(green,16,1,5) position(green,16,1,6) position(red,1,1,0) position(red,2,1,1) position(red,2,2,2) position(red,3,1,5) position(red,3,15,6) position(red,4,1,4) position(red,4,2,3) position(yellow,16,16,0) position(yellow,16,16,1) position(yellow,16,16,2) position(yellow,16,16,3) position(yellow,16,16,4) position(yellow,16,16,5) position(yellow,16,16,6) SAT clingo-5.2.2/app/clingo/tests/lua/setconfig.lp000066400000000000000000000006661320011352300212650ustar00rootroot00000000000000#script (lua) function main(prg) prg:ground({{"step1", {}}}) prg:assign_external(clingo.Function("f"), true) prg.configuration.solve.models = 1 prg:solve() prg:ground({{"step2", {}}}) prg:assign_external(clingo.Function("f"), false) prg.configuration.solve.models = 0 prg:solve() end #end. #program step1. #external f. { a; b; c }. #show f/0. #program step2. #show a : a. #show b : b. #show c : c. clingo-5.2.2/app/clingo/tests/lua/setconfig.sol000066400000000000000000000000571320011352300214410ustar00rootroot00000000000000Step: 1 f Step: 2 a a b a b c a c b b c c SAT clingo-5.2.2/app/clingo/tests/lua/show.lp000066400000000000000000000021271320011352300202560ustar00rootroot00000000000000#script (lua) models = {} function getModels() return models end function normalize(terms) table.sort(terms) return terms end function split(model) terms = {} for i in string.gmatch(tostring(model), "%S+") do terms[#terms+1] = i end table.sort(terms) return terms end function on_model(model) models[#models+1] = clingo.Function("model", split(model)) models[#models+1] = clingo.Function("shown", normalize(model:symbols{shown=true})) models[#models+1] = clingo.Function("atoms", normalize(model:symbols{atoms=true})) models[#models+1] = clingo.Function("terms", normalize(model:symbols{terms=true})) models[#models+1] = clingo.Function("csp", normalize(model:symbols{csp=true})) end function main(prg) prg:ground({{"base", {}}}) prg:solve{on_model=on_model} prg:ground({{"result", {}}}) prg:solve() end #end. $1 $= 11. { b }. c. $x $= 42. $y(1) $= 13. $y(2) $= 23. $z $= 7. #show $1. #show c/0. #show a : b. #show $x/0. #show $y(1) : b. #show $y(2) : not b. #show $y(3) : b. #program result. res(X) :- X = @getModels(). #show res/1. clingo-5.2.2/app/clingo/tests/lua/show.sol000066400000000000000000000012241320011352300204350ustar00rootroot00000000000000Step: 1 1=11 a c x=42 y(1)=13 1=11 c x=42 y(2)=23 Step: 2 1=11 a c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(1)=13 1=11 c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(2)=23 SAT clingo-5.2.2/app/clingo/tests/lua/sokoban.lp000066400000000000000000000062001320011352300207260ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 while true do parts = {} if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) prg:cleanup() else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. #show push_from/4. #show push_to/4. #program base. % convert my instances square(X, Y) :- field(X, Y). target_square(X, Y) :- target(X, Y). initial_box(X, Y) :- stone(X, Y). initial_at(X, Y) :- start(X, Y). % possible directions direction(u). direction(d). direction(r). direction(l). % possible moves dir(u, 0, 1). dir(d, 0, -1). dir(r, 1, 0). dir(l, -1, 0). % reachable places at timestep 0 route(X, Y, 0) :- initial_at(X, Y). route(X, Y, 0) :- dir(D, DX, DY), route(X + DX, Y + DY, 0), not box(X, Y, 0), square(X, Y). % box positions at timestep 0 box(X, Y, 0) :- initial_box(X, Y). #program cumulative(k). % reachable places at timestep k route(X, Y, k) :- at(X, Y, k), square(X, Y). route(X, Y, k) :- dir(D, DX, DY), route(X + DX, Y + DY, k), not box(X, Y, k), square(X, Y). % select a place to push from (must be reachable and have a box to push) 1 { push_from(X, Y, D, k) : square(X, Y), direction(D) } 1. :- push_from(X, Y, D, k), not route(X, Y, k - 1), square(X, Y), direction(D). :- push_from(X, Y, D, k), not box(X + DX, Y + DY, k - 1), square(X, Y), dir(D, DX, DY). % push the box 1 or more fields into direction D (but at least one) push(X, Y, D, k) :- push_from(X, Y, D, k). { push(X + DX, Y + DY, D, k) } :- push(X, Y, D, k), square(X, Y), dir(D, DX, DY). :- push(X, Y, D, k), not square(X + 2 * DX, Y + 2 * DY), dir(D, DX, DY). :- push(X, Y, D, k), box(X + 2 * DX, Y + 2 * DY, k - 1), dir(D, DX, DY). % the last push is the final location (one could try to encode this using a min???) push_to(X + DX, Y + DY, D, k) :- push(X, Y, D, k), not push(X + DX, Y + DY, D, k), dir(D, DX, DY). % the player stands behind the pushed box at(X, Y, k) :- push_to(X, Y, D, k). % put the pushed box at the new location box(X + DX, Y + DY, k) :- push_to(X, Y, D, k), dir(D, DX, DY). % all other boxes stay where they are box(X, Y, k) :- box(X, Y, k - 1), square(X, Y), not push_from(X - DX, Y - DY, D, k) : dir(D, DX, DY). % assert redundant moves :- push_to(X, Y, D, k - 1), push_from(X, Y, D, k). #external volatile(k). % the goal :) :- target_square(X, Y), not box(X, Y, k), volatile(k). #program base. initial_at(1,1). square(1, 1). square(2, 1). square(3, 1). target_square(3, 1). square(4, 1). square(1, 2). square(3, 2). initial_box(3, 2). target_square(3, 2). square(4, 2). square(5, 2). initial_box(5, 2). square(6, 2). square(7, 2). square(1, 3). square(2, 3). initial_box(2, 3). square(3, 3). target_square(3, 3). square(4, 3). initial_box(4, 3). square(5, 3). square(7, 3). square(3, 4). target_square(3, 4). square(5, 4). square(6, 4). square(7, 4). square(3, 5). square(4, 5). square(5, 5). clingo-5.2.2/app/clingo/tests/lua/sokoban.sol000066400000000000000000000032361320011352300211160ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 Step: 10 Step: 11 push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,5) push_from(4,2,r,1) push_from(5,3,l,10) push_from(5,4,d,9) push_from(6,2,l,11) push_from(7,2,l,6) push_to(2,1,r,8) push_to(3,1,l,5) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,11) push_to(4,2,l,6) push_to(4,3,l,10) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9) push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,5) push_from(4,2,r,1) push_from(5,3,l,11) push_from(5,4,d,9) push_from(6,2,l,10) push_from(7,2,l,6) push_to(2,1,r,8) push_to(3,1,l,5) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,10) push_to(4,2,l,6) push_to(4,3,l,11) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9) push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,6) push_from(4,2,r,1) push_from(5,3,l,10) push_from(5,4,d,9) push_from(6,2,l,11) push_from(7,2,l,5) push_to(2,1,r,8) push_to(3,1,l,6) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,11) push_to(4,2,l,5) push_to(4,3,l,10) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9) push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,6) push_from(4,2,r,1) push_from(5,3,l,11) push_from(5,4,d,9) push_from(6,2,l,10) push_from(7,2,l,5) push_to(2,1,r,8) push_to(3,1,l,6) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,10) push_to(4,2,l,5) push_to(4,3,l,11) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9) SAT clingo-5.2.2/app/clingo/tests/lua/sokoban_back.lp000066400000000000000000000077771320011352300217320ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 while true do parts = {} if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) prg:cleanup() else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. #show push_from/3. #show push_to/3. #program base. % convert my instances square(X, Y) :- field(X, Y). target_square(X, Y) :- target(X, Y). initial_box(X, Y) :- stone(X, Y). initial_at(X, Y) :- start(X, Y). box(X,Y,0) :- target_square(X,Y). direction(u). direction(d). direction(r). direction(l). #program cumulative(k). 1{push_to(X,Y,-k) : square(X,Y)}1. :- push_to(X,Y,-k), not box(X,Y,-k+1), square(X,Y). 1{push_dir(D,-k) : direction(D)}1. :- push_to(X,Y,-k), push_dir(u,-k), square(X,Y), not square(X,Y-1). :- push_to(X,Y,-k), push_dir(d,-k), square(X,Y), not square(X,Y+1). :- push_to(X,Y,-k), push_dir(r,-k), square(X,Y), not square(X-1,Y). :- push_to(X,Y,-k), push_dir(l,-k), square(X,Y), not square(X+1,Y). push(X,Y-1,u,-k) :- push_to(X,Y,-k), push_dir(u,-k), square(X,Y). push(X,Y+1,d,-k) :- push_to(X,Y,-k), push_dir(d,-k), square(X,Y). push(X-1,Y,r,-k) :- push_to(X,Y,-k), push_dir(r,-k), square(X,Y). push(X+1,Y,l,-k) :- push_to(X,Y,-k), push_dir(l,-k), square(X,Y). {push(X,Y-1,u,-k)} :- push(X,Y,u,-k), square(X,Y). {push(X,Y+1,d,-k)} :- push(X,Y,d,-k), square(X,Y). {push(X-1,Y,r,-k)} :- push(X,Y,r,-k), square(X,Y). {push(X+1,Y,l,-k)} :- push(X,Y,l,-k), square(X,Y). :- push(X,Y,D,-k), box(X,Y,-k+1), square(X,Y), direction(D). :- push(X,Y,u,-k), square(X,Y), not square(X,Y-1). :- push(X,Y,d,-k), square(X,Y), not square(X,Y+1). :- push(X,Y,r,-k), square(X,Y), not square(X-1,Y). :- push(X,Y,l,-k), square(X,Y), not square(X+1,Y). push_from(X,Y,-k) :- push(X,Y,u,-k), not push(X,Y-1,u,-k), square(X,Y). push_from(X,Y,-k) :- push(X,Y,d,-k), not push(X,Y+1,d,-k), square(X,Y). push_from(X,Y,-k) :- push(X,Y,r,-k), not push(X-1,Y,r,-k), square(X,Y). push_from(X,Y,-k) :- push(X,Y,l,-k), not push(X+1,Y,l,-k), square(X,Y). box(X,Y,-k) :- push_from(X,Y,-k), square(X,Y). box(X,Y,-k) :- box(X,Y,-k+1), not push_to(X,Y,-k), square(X,Y). at(X,Y-1,-k) :- push_from(X,Y,-k), push_dir(u,-k), square(X,Y). at(X,Y+1,-k) :- push_from(X,Y,-k), push_dir(d,-k), square(X,Y). at(X-1,Y,-k) :- push_from(X,Y,-k), push_dir(r,-k), square(X,Y). at(X+1,Y,-k) :- push_from(X,Y,-k), push_dir(l,-k), square(X,Y). :- at(X,Y,-k), box(X,Y,-k+1), square(X,Y). route(X,Y,-k) :- at(X,Y,-k), square(X,Y). route(X,Y,-k) :- route(X+1,Y,-k), not box(X,Y,-k), square(X,Y). route(X,Y,-k) :- route(X-1,Y,-k), not box(X,Y,-k), square(X,Y). route(X,Y,-k) :- route(X,Y+1,-k), not box(X,Y,-k), square(X,Y). route(X,Y,-k) :- route(X,Y-1,-k), not box(X,Y,-k), square(X,Y). :- push_to(X,Y,-k), push_dir(u,-k), not route(X,Y-1,-k+1), square(X,Y), k > 1. :- push_to(X,Y,-k), push_dir(d,-k), not route(X,Y+1,-k+1), square(X,Y), k > 1. :- push_to(X,Y,-k), push_dir(r,-k), not route(X-1,Y,-k+1), square(X,Y), k > 1. :- push_to(X,Y,-k), push_dir(l,-k), not route(X+1,Y,-k+1), square(X,Y), k > 1. :- push_to(X,Y,-k), push_from(X,Y,-k+1), push_dir(D,-k), push_dir(D,-k+1), direction(D), square(X,Y), k > 1. #external volatile(k). :- initial_box(X,Y), not box(X,Y,-k), volatile(k). :- initial_at(X,Y), not route(X,Y,-k), volatile(k). #program base. initial_at(1,1). square(1, 1). square(2, 1). square(3, 1). target_square(3, 1). square(4, 1). square(1, 2). square(3, 2). initial_box(3, 2). target_square(3, 2). square(4, 2). square(5, 2). initial_box(5, 2). square(6, 2). square(7, 2). square(1, 3). square(2, 3). initial_box(2, 3). square(3, 3). target_square(3, 3). square(4, 3). initial_box(4, 3). square(5, 3). square(7, 3). square(3, 4). target_square(3, 4). square(5, 4). square(6, 4). square(7, 4). square(3, 5). square(4, 5). square(5, 5). clingo-5.2.2/app/clingo/tests/lua/sokoban_back.sol000066400000000000000000000031061320011352300220720ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 Step: 10 Step: 11 push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-6) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-1) push_from(4,3,-10) push_from(5,2,-11) push_from(5,2,-2) push_from(5,3,-3) push_from(6,2,-7) push_to(2,1,-6) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-2) push_to(3,2,-7) push_to(3,3,-1) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11) push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-6) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-10) push_from(4,3,-2) push_from(5,2,-1) push_from(5,2,-11) push_from(5,3,-3) push_from(6,2,-7) push_to(2,1,-6) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-1) push_to(3,2,-7) push_to(3,3,-2) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11) push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-7) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-1) push_from(4,3,-10) push_from(5,2,-11) push_from(5,2,-2) push_from(5,3,-3) push_from(6,2,-6) push_to(2,1,-7) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-2) push_to(3,2,-6) push_to(3,3,-1) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11) push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-7) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-10) push_from(4,3,-2) push_from(5,2,-1) push_from(5,2,-11) push_from(5,3,-3) push_from(6,2,-6) push_to(2,1,-7) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-1) push_to(3,2,-6) push_to(3,3,-2) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11) SAT clingo-5.2.2/app/clingo/tests/lua/sokoban_para.lp000066400000000000000000000106051320011352300217350ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 while true do parts = {} if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) prg:cleanup() else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. #show push_box/4. #show push_to/4. #show at/3. #program base. % possible directions direction(u). direction(d). direction(r). direction(l). % possible moves dir(u, 0, 1). dir(d, 0, -1). dir(r, 1, 0). dir(l, -1, 0). % box positions at timestep 0 box(X, Y, 0) :- initial_box(X, Y). % player at timestep 0 at(X, Y, 0) :- initial_at(X, Y). #program cumulative(k). % reachable places at timestep k routePre(X, Y, k) :- at(X, Y, k - 1), square(X, Y). routePre(X, Y, k) :- dir(D, DX, DY), routePre(X + DX, Y + DY, k), not box(X, Y, k - 1), square(X, Y). routePost(X, Y, k) :- at(X, Y, k), square(X, Y). routePost(X, Y, k) :- dir(D, DX, DY), routePost(X + DX, Y + DY, k), not box(X, Y, k - 1), not box(X, Y, k), square(X, Y). % move the player (this could be restricted to moves behind boxes) 1 { at(X, Y, k) : square(X, Y) } 1. :- not routePre(X, Y, k), at(X, Y, k). :- box(X, Y, k), at(X, Y, k). % select at least one box to push into exactly one direction (must be reachable and have a box to push) 1 { push_box(X, Y, D, k) : square(X, Y), direction(D) }. :- push_box(X, Y, D, k), not routePre(X - DX, Y - DY, k), dir(D, DX, DY). :- push_box(X, Y, D, k), not routePost(X - DX, Y - DY, k), dir(D, DX, DY). :- push_box(X, Y, D, k), not box(X, Y, k - 1). :- push_box(X, Y, D1, k), push_box(X, Y, D2, k), D1 != D2. % push the box 1 or more fields into direction D (but at least one) push(X + DX, Y + DY, D, k) :- push_box(X, Y, D, k), dir(D, DX, DY). { push(X + DX, Y + DY, D, k) } :- push(X, Y, D, k), square(X, Y), dir(D, DX, DY). :- push(X, Y, D, k), not square(X, Y). :- push(X, Y, D, k), box(X, Y, k - 1). % the last push is the final location push_to(X, Y, D, k) :- push(X, Y, D, k), not push(X + DX, Y + DY, D, k), dir(D, DX, DY). :- push_to(X, Y, D1, k), push_to(X, Y, D2, k), D1 != D2. % put the pushed box at the new location box(X, Y, k) :- push_to(X, Y, D, k). % all other boxes stay where they are box(X, Y, k) :- box(X, Y, k - 1), square(X, Y), not push_box(X, Y, D, k) : direction(D). % assert redundant moves % :- push_box(X, Y, D, k - 1), push_from(X, Y, D, k). #external volatile(k). % the goal :) :- target_square(X, Y), not box(X, Y, k), volatile(k). % restrict search space a little :- not at(1,1,k), k==0. :- not at(1,1,k), k==6. :- not at(1,1,k), k==8. :- not at(7,2,k), k==7. :- not at(1,3,k), k==1. :- not at(1,3,k), k==3. :- not at(2,3,k), k==5. :- not at(3,3,k), k==2. :- not at(5,4,k), k==9. :- not at(5,5,k), k==4. :- not push_box(3,2,u,k), k==7. :- not push_box(5,2,r,k), k==1. :- not push_box(4,3,r,k), k==2. :- not push_box(5,2,r,k), k==3. :- not push_box(2,3,r,k), k==3. :- not push_box(5,2,r,k), k==5. :- not push_box(2,1,r,k), k==8. :- not push_box(3,2,d,k), k==4. :- not push_box(5,3,d,k), k==9. :- not push_box(6,2,l,k), k==2. :- not push_box(6,2,l,k), k==4. :- not push_box(3,1,l,k), k==5. :- not push_box(6,2,l,k), k==6. :- not push_box(5,2,l,k), k==10. :- not push_box(4,3,l,k), k==10. :- not push_to(3,4,u,k), k==7. :- not push_to(6,2,r,k), k==1. :- not push_to(5,3,r,k), k==2. :- not push_to(6,2,r,k), k==3. :- not push_to(4,3,r,k), k==3. :- not push_to(6,2,r,k), k==5. :- not push_to(3,1,r,k), k==8. :- not push_to(3,1,d,k), k==4. :- not push_to(5,2,d,k), k==9. :- not push_to(5,2,l,k), k==2. :- not push_to(5,2,l,k), k==4. :- not push_to(2,1,l,k), k==5. :- not push_to(3,2,l,k), k==6. :- not push_to(3,2,l,k), k==10. :- not push_to(3,3,l,k), k==10. #program base. initial_at(1,1). square(1, 1). square(2, 1). square(3, 1). target_square(3, 1). square(4, 1). square(1, 2). square(3, 2). initial_box(3, 2). target_square(3, 2). square(4, 2). square(5, 2). initial_box(5, 2). square(6, 2). square(7, 2). square(1, 3). square(2, 3). initial_box(2, 3). square(3, 3). target_square(3, 3). square(4, 3). initial_box(4, 3). square(5, 3). square(7, 3). square(3, 4). target_square(3, 4). square(5, 4). square(6, 4). square(7, 4). square(3, 5). square(4, 5). square(5, 5). clingo-5.2.2/app/clingo/tests/lua/sokoban_para.sol000066400000000000000000000145251320011352300221240ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 Step: 10 at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(3,5,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(4,5,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,3,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,10) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(6,2,10) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(6,4,10) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(7,2,10) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(7,2,7) at(7,3,10) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(7,2,7) at(7,4,10) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5) SAT clingo-5.2.2/app/clingo/tests/lua/solitaire_para.lp000066400000000000000000000072741320011352300223040ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 while true do parts = {} if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable or step == 13 then break end step = step + 1 end end #end. #show jump/4. #const n=31. #program base. % ------- % |o|o|o| % ------- % |o|o|o| % --------------- % |o|o|o|o|o|o|o| % --------------- % |o|o|o| |o|o|o| % --------------- % |o|o|o|o|o|o|o| % --------------- % |o|o|o| % ------- % |o|o|o| % ------- % % % the field field(0, 0). field(X, Y) :- stone(X, Y). % the 3x3 quads stone(-1 .. 1, -3 .. -1). stone(-3 .. -1, -1 .. 1). stone( 1 .. 3, -1 .. 1). stone(-1 .. 1, 1 .. 3). dir(west;east;north;south). dir(west , -1, 0). dir(east , 1, 0). dir(north, 0, -1). dir(south, 0, 1). stone(X, Y, 0) :- stone(X, Y). % possible jumps field(X, Y, D) :- field(X, Y), field(X + 2 * DX, Y + 2 * DY), dir(D, DX, DY). #program cumulative(t). % fix the first jump to avoid symmetries jump(0,-2,south,t) :- t == 1. % choose one stone 1 { jump(X, Y, D, t) : field(X, Y, D) }. % fail if no stone at position :- jump(X, Y, D, t), not stone(X, Y, t - 1). % fail if stone at target :- jump(X, Y, D, t), stone(X + 2 * DX, Y + 2 * DY, t - 1), dir(D, DX, DY). % fail if no stone to jump over :- jump(X, Y, D, t), not stone(X + DX, Y + DY, t - 1), dir(D, DX, DY). % a stone may not jump in two directions :- jump(X, Y, D1, t), jump(X, Y, D2, t), D1 != D2. % fail if two stones jumped over the same location :- jump(X1, Y1, D1, t), jump(X2, Y2, D2, t), dir(D1, DX1, DY1), dir(D2, DX2, DY2), X1 + DX1 == X2 + DX2, Y1 + DY1 == Y2 + DY2, D1 != D2. % fail if two stones jumped at the same target :- jump(X1, Y1, D1, t), jump(X2, Y2, D2, t), dir(D1, DX1, DY1), dir(D2, DX2, DY2), X1 + 2 * DX1 == X2 + 2 * DX2, Y1 + 2 * DY1 == Y2 + 2 * DY2, D1 != D2. % a removed stone may not jump :- jump(X, Y, D, t), removed(X, Y, t). % place the new stone stone(X + 2 * DX, Y + 2 * DY, t) :- jump(X, Y, D, t), dir(D, DX, DY). % mark the moved stone jumped(X, Y, t) :- jump(X, Y, D, t). % remove the stone removed(X + DX, Y + DY, t) :- jump(X, Y, D, t), dir(D, DX, DY). % keep other stones stone(X, Y, t) :- field(X, Y), stone(X, Y, t - 1), not jumped(X, Y, t), not removed(X, Y, t). % restrict search space a little :- not jump(0,-2,south,t), t==1. :- not jump(0,-1,east,t), t==4. :- not jump(-1,1,east,t), t==4. :- not jump(-2,-1,east,t), t==5. :- not jump(-1,-3,east,t), t==6. :- not jump(-3,0,east,t), t==7. :- not jump(-3,1,east,t), t==7. :- not jump(-3,-1,east,t), t==8. :- not jump(0,1,east,t), t==10. :- not jump(-1,2,east,t), t==11. :- not jump(1,-3,south,t), t==5. :- not jump(1,-3,south,t), t==7. :- not jump(-1,0,south,t), t==8. :- not jump(-1,-2,south,t), t==9. :- not jump(3,-1,south,t), t==9. :- not jump(0,-1,south,t), t==9. :- not jump(-1,0,south,t), t==10. :- not jump(2,-1,west,t), t==2. :- not jump(0,-1,west,t), t==7. :- not jump(2,-1,west,t), t==8. :- not jump(3,1,west,t), t==11. :- not jump(2,0,west,t), t==13. :- not jump(1,1,north,t), t==3. :- not jump(-1,3,north,t), t==5. :- not jump(1,2,north,t), t==5. :- not jump(1,0,north,t), t==6. :- not jump(-1,1,north,t), t==6. :- not jump(-1,3,north,t), t==9. :- not jump(1,2,north,t), t==12. #external volatile(t). % there shall be at least n free places :- { not stone(X, Y, t) : field(X, Y) } n, volatile(t). % the last stone shall be in the center :- not stone(0, 0, t), volatile(t). clingo-5.2.2/app/clingo/tests/lua/solitaire_para.sol000066400000000000000000000122361320011352300224600ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 Step: 10 Step: 11 Step: 12 Step: 13 jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,6) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,6) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,6) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,7) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,6) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,8) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,7) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,6) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,7) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,7) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,7) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,8) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,8) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,6) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,8) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,7) jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,8) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,8) SAT clingo-5.2.2/app/clingo/tests/lua/solitaire_sort.lp000066400000000000000000000161101320011352300223350ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 while true do parts = {} if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. #const parallel=yes. % replace by anything else than "yes" to disable parallel jumps #const clear=32. % (minimum) number of cleared grid cells in goal configuration #program base. % grid cells gc(f(c,1..2,3..5)). gc(f(c,3..5,1..7)). gc(f(c,6..7,3..5)). % initial configuration in(f(c,3,1)). in(f(c,4,1)). in(f(c,5,1)). in(f(c,3,2)). in(f(c,4,2)). in(f(c,5,2)). in(f(c,1,3)). in(f(c,2,3)). in(f(c,3,3)). in(f(c,4,3)). in(f(c,5,3)). in(f(c,6,3)). in(f(c,7,3)). in(f(c,1,4)). in(f(c,2,4)). in(f(c,3,4)). in(f(c,5,4)). in(f(c,6,4)). in(f(c,7,4)). in(f(c,1,5)). in(f(c,2,5)). in(f(c,3,5)). in(f(c,4,5)). in(f(c,5,5)). in(f(c,6,5)). in(f(c,7,5)). in(f(c,3,6)). in(f(c,4,6)). in(f(c,5,6)). in(f(c,3,7)). in(f(c,4,7)). in(f(c,5,7)). % goal configurations(s) on(f(c,4,4)). un(clear). % generic predicates for sorting sort(I,J) :- sort(I), sort(J), I < J, #false : sort(K), I < K, K < J. prec(I,J) :- sort(I,J), not lead(J). succ(J) :- prec(_,J). succ(I,J) :- prec(I,J), succ(I). % sort possible jumps dir(-1,0). dir(0,-1). dir(0,1). dir(1,0). sort(f(j,X-D,Y-E,X+D,Y+E)) :- gc(f(c,X,Y)), dir(D,E), gc(f(c,X-D,Y-E)), gc(f(c,X+D,Y+E)). lead(f(j,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)), not sort(f(j,V,W,VV,WW),f(j,X,Y,XX,YY)) : sort(f(j,V,W,VV,WW),f(j,X,Y,XX,YY)). % sort jumps wrt target grid cells sort(f(i,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)). lead(f(i,X,Y,XX,YY)) :- sort(f(i,X,Y,XX,YY)), not sort(f(i,X,Y,VV,WW),f(i,X,Y,XX,YY)) : sort(f(i,X,Y,VV,WW),f(i,X,Y,XX,YY)). % sort jumps wrt cleared grid cells sort(f(k,XX,YY,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)). sort(f(k,(X+XX)/2,(Y+YY)/2,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)). lead(f(k,XXX,YYY,X,Y,XX,YY)) :- sort(f(k,XXX,YYY,X,Y,XX,YY)), not sort(f(k,XXX,YYY,V,W,VV,WW),f(k,XXX,YYY,X,Y,XX,YY)) : sort(f(k,XXX,YYY,V,W,VV,WW),f(k,XXX,YYY,X,Y,XX,YY)). % sort jumps wrt smallest cleared or target grid cells (if parallel moves disabled) sort(f(l,0,XX,YY,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)), (XX,YY) < (X,Y), parallel != yes. sort(f(l,1,-X,-Y,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)), (X,Y) < (XX,YY), parallel != yes. lead(f(l,L,AA,BB,X,Y,XX,YY)) :- sort(f(l,L,AA,BB,X,Y,XX,YY)), not sort(f(l,M,CC,DD,V,W,VV,WW),f(l,L,AA,BB,X,Y,XX,YY)) : sort(f(l,M,CC,DD,V,W,VV,WW),f(l,L,AA,BB,X,Y,XX,YY)). % calculate grid symmetries axis(x,M+N) :- M = #min { X : gc(f(c,X,_)) }, N = #max { X : gc(f(c,X,_)) }. axis(y,M+N) :- M = #min { Y : gc(f(c,_,Y)) }, N = #max { Y : gc(f(c,_,Y)) }. swap(0,f(c,X,Y),f(c,X,Y)) :- gc(f(c,X,Y)). swap(1,f(c,X,Y),f(c,N-X,Y)) :- gc(f(c,X,Y)), axis(x,N). swap(S+2,f(c,X,Y),f(c,XX,N-Y)) :- swap(S,f(c,X,Y),f(c,XX,Y)), axis(y,N), S < 2. swap(S+4,f(c,X,Y),f(c,YY,XX)) :- swap(S,f(c,X,Y),f(c,XX,YY)), S < 4. sort(f(s,S,XX,YY,X,Y)) :- swap(S,f(c,X,Y),f(c,XX,YY)), (X,Y) != (XX,YY). lead(f(s,S,XX,YY,X,Y)) :- sort(f(s,S,XX,YY,X,Y)), not sort(f(s,S,VV,WW,V,W),f(s,S,XX,YY,X,Y)) : sort(f(s,S,VV,WW,V,W),f(s,S,XX,YY,X,Y)). asym(f(s,S,XX,YY,X,Y)) :- sort(f(s,S,XX,YY,X,Y)), not sort(f(s,S,X,Y,XX,YY)). less(f(s,S,XX,YY,X,Y)) :- sort(f(s,S,XX,YY,X,Y)), (XX,YY) < (X,Y). here(I) :- less(I), lead(I). here(I,J) :- less(J), prec(I,J). more(I,J) :- prec(I,J), here(J,_). more(I,J) :- prec(I,J), more(J,_). more(I) :- more(I,_), lead(I). % initial configuration hold(C,0) :- in(C). #program cumulative(t). % generate jumps poss(f(j,X,Y,XX,YY),t) :- sort(f(j,X,Y,XX,YY)), not hold(f(c,X,Y),t-1), hold(f(c,XXX,YYY),t-1) : sort(f(k,XXX,YYY,X,Y,XX,YY)). { move(J,t) } :- poss(J,t). % propagate effects of jumps fill(J,t) :- move(J,t), succ(J). fill(f(i,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), succ(f(i,X,Y,XX,YY)). fill(f(k,XXX,YYY,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), succ(f(k,XXX,YYY,X,Y,XX,YY)). fill(f(l,L,AA,BB,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), succ(f(l,L,AA,BB,X,Y,XX,YY)). fill(I,t) :- fill(J,t), succ(I,J). grep(I,t) :- fill(J,t), prec(I,J), lead(I). grep(J,t) :- move(J,t), lead(J). grep(f(i,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), lead(f(i,X,Y,XX,YY)). grep(f(k,XXX,YYY,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), lead(f(k,XXX,YYY,X,Y,XX,YY)). % assert application of some jump :- lead(f(j,X,Y,XX,YY)), not grep(f(j,X,Y,XX,YY),t). % forbid parallel jumps (if disabled) :- prec(I,J), move(I,t), fill(J,t), parallel != yes. % forbid conflicting parallel jumps (if parallel jumps not disabled) :- prec(f(i,X,Y,XX,YY),J), move(f(j,X,Y,XX,YY),t), fill(J,t), parallel == yes. :- prec(f(k,XXX,YYY,X,Y,XX,YY),J), move(f(j,X,Y,XX,YY),t), fill(J,t), parallel == yes. % successor configuration hold(f(c,X,Y),t) :- grep(f(i,X,Y,_,_),t). hold(f(c,XXX,YYY),t) :- hold(f(c,XXX,YYY),t-1), lead(f(k,XXX,YYY,X,Y,XX,YY)), not grep(f(k,XXX,YYY,X,Y,XX,YY),t). % assert order among independent jumps :- move(I,t), poss(I,t-1), parallel == yes. :- move(f(j,X,Y,XX,YY),t), poss(f(j,X,Y,XX,YY),t-1), parallel != yes, fill(f(l,L,AA,BB,X,Y,XX,YY),t-1) : succ(f(l,L,AA,BB,X,Y,XX,YY)). % assert lexicographically smallest successor configuration wrt symmetric configurations diff(S,t) :- sort(f(s,S,XX,YY,X,Y)), hold(f(c,X,Y),t-1), not hold(f(c,XX,YY),t-1). :- asym(f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t-1), not hold(f(c,X,Y),t-1), not diff(S,t). comp(S,f(s,S,XX,YY,X,Y),t) :- more(f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t). comp(S,f(s,S,XX,YY,X,Y),t) :- more(f(s,S,XX,YY,X,Y)), not hold(f(c,X,Y),t). comp(S,f(s,S,XX,YY,X,Y),t) :- more(I,f(s,S,XX,YY,X,Y)), comp(S,I,t), hold(f(c,XX,YY),t). comp(S,f(s,S,XX,YY,X,Y),t) :- more(I,f(s,S,XX,YY,X,Y)), comp(S,I,t), not hold(f(c,X,Y),t). :- here(f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t), not hold(f(c,X,Y),t), not diff(S,t). :- here(I,f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t), not hold(f(c,X,Y),t), not diff(S,t), comp(S,I,t). % limit search space ... :- not move(f(j,4,4,2,4),t), t == 1. :- not move(f(j,5,3,5,1),t), t == 5. :- not move(f(j,5,1,3,1),t), t == 6. :- not move(f(j,5,2,5,4),t), t == 6. :- not move(f(j,5,5,7,5),t), t == 6. :- not move(f(j,6,5,4,5),t), t == 7. :- not move(f(j,5,3,5,1),t), t == 7. :- not move(f(j,4,4,4,6),t), t == 13. #external volatile(t). % assert goal configuration(s) :- on(C), not hold(C,t), volatile(t). :- un(N), not N { not hold(C,t) : gc(C) }, volatile(t). #show move/2. clingo-5.2.2/app/clingo/tests/lua/solitaire_sort.sol000066400000000000000000000077161320011352300225330ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 Step: 10 Step: 11 Step: 12 Step: 13 move(f(j,1,3,1,5),4) move(f(j,2,3,4,3),4) move(f(j,2,5,4,5),10) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,1,3),5) move(f(j,3,3,5,3),10) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),9) move(f(j,3,5,3,3),11) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,3,4,5),5) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,2,5),6) move(f(j,4,5,6,5),9) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,3,7,3),9) move(f(j,5,4,5,6),5) move(f(j,5,4,7,4),7) move(f(j,5,5,5,3),8) move(f(j,5,5,7,5),6) move(f(j,6,5,4,5),7) move(f(j,1,3,1,5),4) move(f(j,2,3,4,3),4) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,1,3),5) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),8) move(f(j,3,5,3,7),10) move(f(j,3,5,3,7),8) move(f(j,3,6,3,4),7) move(f(j,3,6,3,4),9) move(f(j,3,7,5,7),9) move(f(j,4,3,6,3),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,4,6,4),10) move(f(j,4,5,2,5),12) move(f(j,4,5,4,3),9) move(f(j,4,6,4,4),11) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,4,5,6),5) move(f(j,5,4,5,6),9) move(f(j,5,5,7,5),6) move(f(j,5,5,7,5),8) move(f(j,5,6,3,6),6) move(f(j,6,5,4,5),7) move(f(j,7,5,7,3),7) move(f(j,1,3,1,5),6) move(f(j,2,3,4,3),6) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),5) move(f(j,3,3,1,3),7) move(f(j,3,3,3,5),3) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),4) move(f(j,3,5,3,7),4) move(f(j,3,5,3,7),6) move(f(j,3,6,3,4),5) move(f(j,3,7,5,7),5) move(f(j,4,3,6,3),11) move(f(j,4,3,6,3),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),8) move(f(j,4,5,4,3),12) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,3,3),9) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,4,5,6),5) move(f(j,5,5,7,5),6) move(f(j,5,5,7,5),8) move(f(j,6,3,6,5),10) move(f(j,6,5,4,5),7) move(f(j,6,5,4,5),9) move(f(j,7,5,7,3),7) move(f(j,1,3,1,5),7) move(f(j,2,3,4,3),10) move(f(j,2,3,4,3),7) move(f(j,2,4,4,4),4) move(f(j,2,5,2,3),11) move(f(j,3,3,1,3),6) move(f(j,3,3,1,3),8) move(f(j,3,4,3,2),5) move(f(j,3,4,5,4),2) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,3,6,3),4) move(f(j,4,3,6,3),9) move(f(j,4,4,2,4),1) move(f(j,4,4,4,2),3) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,2,5),6) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,4,5,6),3) move(f(j,5,5,7,5),4) move(f(j,5,5,7,5),6) move(f(j,6,3,6,5),8) move(f(j,6,5,4,5),5) move(f(j,6,5,4,5),7) move(f(j,7,5,7,3),5) move(f(j,2,4,4,4),3) move(f(j,2,5,4,5),10) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,5,3),10) move(f(j,3,4,1,4),7) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),9) move(f(j,3,4,3,6),4) move(f(j,3,5,1,5),5) move(f(j,3,5,3,3),11) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),6) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,6,5),9) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,3,7,3),9) move(f(j,5,4,5,6),5) move(f(j,5,4,7,4),7) move(f(j,5,5,5,3),8) move(f(j,5,5,7,5),6) move(f(j,6,5,4,5),7) move(f(j,2,4,4,4),3) move(f(j,2,5,4,5),10) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,5,3),10) move(f(j,3,4,1,4),9) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),7) move(f(j,3,4,3,6),4) move(f(j,3,5,1,5),5) move(f(j,3,5,3,3),11) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),6) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,6,5),9) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,3,7,3),9) move(f(j,5,4,5,6),5) move(f(j,5,4,7,4),7) move(f(j,5,5,5,3),8) move(f(j,5,5,7,5),6) move(f(j,6,5,4,5),7) SAT clingo-5.2.2/app/clingo/tests/lua/test.lp000066400000000000000000000022711320011352300202550ustar00rootroot00000000000000#script (lua) function map(func, array) for i,v in ipairs(array) do array[i] = func(v) end return array end function sorted(t) table.sort(t) return t end function on_model(x) print("Answer: 42") print( "hasA(" .. tostring(x:contains(clingo.Function("a"))) .. ") " .. "hasVolatile(" .. tostring(x:contains(clingo.Function("volatile", {9}))) .. ") " .. "model(" .. table.concat(sorted(map(tostring, x:symbols{shown=true})), ",") .. ") ") io.flush() end function main (prg) n = prg:get_const("n").number parts = {} parts[#parts+1] = {"base", {}} prg:ground(parts) prg:solve() parts = {} prg:add("test", {"x"}, "test(x).") parts[#parts+1] = {"test", {clingo.Function("f", {1,2})}} for i=1,n do parts[#parts+1] = {"cumulative", {i}} prg:ground(parts) parts = {} ret = prg:solve{on_model=on_model} print("Answer: 42") print(tostring(ret)) io.flush() end end #end. #const n = 10. #program base. a. #program cumulative(k). 1 { c(k) } 1. q(k) :- c(k). r(k,X) :- test(X). #external volatile(k). :- not c(5), not volatile(k). volatile(k-1). clingo-5.2.2/app/clingo/tests/lua/test.sol000066400000000000000000000070331320011352300204400ustar00rootroot00000000000000Step: 1 a Step: 2 UNSAT Step: 3 UNSAT Step: 4 UNSAT Step: 5 UNSAT Step: 6 SAT a c(1) c(2) c(3) c(4) c(5) q(1) q(2) q(3) q(4) q(5) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),q(1),q(2),q(3),q(4),q(5),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4)) Step: 7 SAT a c(1) c(2) c(3) c(4) c(5) c(6) q(1) q(2) q(3) q(4) q(5) q(6) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),q(1),q(2),q(3),q(4),q(5),q(6),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5)) Step: 8 SAT a c(1) c(2) c(3) c(4) c(5) c(6) c(7) q(1) q(2) q(3) q(4) q(5) q(6) q(7) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),q(1),q(2),q(3),q(4),q(5),q(6),q(7),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6)) Step: 9 SAT a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7)) Step: 10 SAT a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8)) Step: 11 SAT a c(1) c(10) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(10) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(10,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8) volatile(9) hasA(true) hasVolatile(true) model(a,c(1),c(10),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(10),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(10,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8),volatile(9)) SAT clingo-5.2.2/app/clingo/tests/lua/theory-term-types.lp000066400000000000000000000006051320011352300227160ustar00rootroot00000000000000#script (lua) clingo = require("clingo") function types() return { tostring(clingo.TheoryTermType.Tuple), tostring(clingo.TheoryTermType.List), tostring(clingo.TheoryTermType.Set), tostring(clingo.TheoryTermType.Function), tostring(clingo.TheoryTermType.Symbol), tostring(clingo.TheoryTermType.Number), } end #end. p(@types()). clingo-5.2.2/app/clingo/tests/lua/theory-term-types.sol000066400000000000000000000001201320011352300230700ustar00rootroot00000000000000Step: 1 p("Function") p("List") p("Number") p("Set") p("Symbol") p("Tuple") SAT clingo-5.2.2/app/clingo/tests/lua/theory.lp000066400000000000000000000030031320011352300206020ustar00rootroot00000000000000#script (lua) clingo = require("clingo") t = {} function get() return t end function convert_term(t) if t.type == clingo.TheoryTermType.Function then a = {} for i, x in ipairs(t.arguments) do a[#a+1] = convert_term(x) end return clingo.Tuple({t.name, clingo.Tuple(a)}) elseif t.type == clingo.TheoryTermType.Number then return t.number elseif t.type == clingo.TheoryTermType.Symbol then return t.name else return clingo.Function("unimplemented") end end function main(c) c:ground({{"base",{}}}) for x in c.theory_atoms do r = {} r[#r+1] = convert_term(x.term) e = {} for i,y in ipairs(x.elements) do cond = {} for i, z in ipairs(y.condition) do cond[#cond+1] = "n/a" end Tuple = {} for i, z in ipairs(y.terms) do Tuple[#Tuple+1] = convert_term(z) end e[#e+1] = clingo.Tuple({clingo.Tuple(Tuple), clingo.Tuple(cond)}) end r[#r+1] = clingo.Tuple(e) if x.guard ~= nil then r[#r+1] = clingo.Tuple({x.guard[1], convert_term(x.guard[2])}) end t[#t+1] = clingo.Tuple(r) end c:ground({{"theory",{}}}) c:solve() end #end. #theory t { t { + : 1, binary, left; - : 1, binary, left }; &a/0: t, any; &b/0: t, {=}, t, any }. 2 { p; q } 2. &a{ a+b : p,q; 1,c-d}. &a{ 1,c-d}. &b{ } = a+b. #program theory. p(@get()). clingo-5.2.2/app/clingo/tests/lua/theory.sol000066400000000000000000000002361320011352300207710ustar00rootroot00000000000000Step: 1 p p(("a",(((("+",("a","b")),),("n/a","n/a")),((1,("-",("c","d"))),())))) p(("a",(((1,("-",("c","d"))),()),))) p(("b",(),("=",("+",("a","b"))))) q SAT clingo-5.2.2/app/clingo/tests/lua/toh.lp000066400000000000000000000042241320011352300200700ustar00rootroot00000000000000#script (lua) function main(prg) step = 1 while true do parts = {} if step > 1 then prg:release_external(clingo.Function("volatile", {step-1})) else parts[#parts+1] = {"base", {}} end parts[#parts+1] = {"cumulative", {step}} prg:ground(parts) prg:assign_external(clingo.Function("volatile", {step}), true) ret = prg:solve() if ret.satisfiable then break end step = step + 1 end end #end. #show put/3. #program cumulative(k). 1{move(N,k) : disk(N), N > 3}1. 1{where(N,k) : disk(N)}1. on(M,N,k) :- disk(M;N), move(M,k), where(N,k). on(M,N,k) :- disk(M;N), on(M,N,k-1), not move(M,k). :- disk(N), move(N,k-1), move(N,k). :- disk(M;N), on(M,N,k-1), move(N,k). :- disk(M;N), on(M,N,k-1), where(N,k). :- disk(M;N), on(M,N,k), M <= N. put(M,N,k) :- disk(M;N), move(M,k), where(N,k). #external volatile(k). :- goal_on(X,Y), not on(X,Y,k), volatile(k). % restrict search space a little %:- not put(9,8,k), k==1. %:- not put(4,3,k), k==2. %:- not put(9,4,k), k==3. %:- not put(8,1,k), k==4. :- not put(9,8,k), k==5. %:- not put(7,4,k), k==6. %:- not put(9,6,k), k==7. %:- not put(8,7,k), k==8. %:- not put(9,8,k), k==9. %:- not put(6,1,k), k==10. %:- not put(9,6,k), k==11. %:- not put(8,5,k), k==12. %:- not put(9,8,k), k==13. %:- not put(7,6,k), k==14. %:- not put(9,4,k), k==15. :- not put(8,7,k), k==16. %:- not put(9,8,k), k==17. %:- not put(5,4,k), k==18. %:- not put(9,2,k), k==19. %:- not put(8,5,k), k==20. :- not put(9,8,k), k==21. %:- not put(7,2,k), k==22. %:- not put(9,6,k), k==23. %:- not put(8,7,k), k==24. %:- not put(9,8,k), k==25. :- not put(6,5,k), k==26. %:- not put(9,6,k), k==27. %:- not put(8,1,k), k==28. %:- not put(9,8,k), k==29. :- not put(7,6,k), k==30. %:- not put(9,2,k), k==31. %:- not put(8,7,k), k==32. %:- not put(9,8,k), k==33. #program base. on(X,Y,0) :- init_on(X,Y). disk(1). disk(2). disk(3). disk(4). disk(5). disk(6). disk(7). disk(8). disk(9). init_on(9,4). init_on(4,1). init_on(8,7). init_on(7,6). init_on(6,5). init_on(5,2). goal_on(4,3). goal_on(5,4). goal_on(6,5). goal_on(7,6). goal_on(8,7). goal_on(9,8). clingo-5.2.2/app/clingo/tests/lua/toh.sol000066400000000000000000000012471320011352300202540ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 Step: 10 Step: 11 Step: 12 Step: 13 Step: 14 Step: 15 Step: 16 Step: 17 Step: 18 Step: 19 Step: 20 Step: 21 Step: 22 Step: 23 Step: 24 Step: 25 Step: 26 Step: 27 Step: 28 Step: 29 Step: 30 Step: 31 Step: 32 Step: 33 put(4,3,2) put(5,4,18) put(6,1,10) put(6,5,26) put(7,2,22) put(7,4,6) put(7,6,14) put(7,6,30) put(8,1,28) put(8,1,4) put(8,5,12) put(8,5,20) put(8,7,16) put(8,7,24) put(8,7,32) put(8,7,8) put(9,2,19) put(9,2,31) put(9,4,15) put(9,4,3) put(9,6,11) put(9,6,23) put(9,6,27) put(9,6,7) put(9,8,1) put(9,8,13) put(9,8,17) put(9,8,21) put(9,8,25) put(9,8,29) put(9,8,33) put(9,8,5) put(9,8,9) SAT clingo-5.2.2/app/clingo/tests/lua/unsat-sync.lp000066400000000000000000000001611320011352300213760ustar00rootroot00000000000000:-. #script (lua) function main(prg) prg:ground({{"base", {}}}) prg:solve() prg:solve() end #end. clingo-5.2.2/app/clingo/tests/lua/unsat-sync.sol000066400000000000000000000000261320011352300215600ustar00rootroot00000000000000Step: 1 Step: 2 UNSAT clingo-5.2.2/app/clingo/tests/python/000077500000000000000000000000001320011352300174775ustar00rootroot00000000000000clingo-5.2.2/app/clingo/tests/python/assumptions1.lp000066400000000000000000000002621320011352300225020ustar00rootroot00000000000000#script (python) import sys from clingo import Function def main(prg): prg.ground([("base", [])]) prg.solve(assumptions=[(Function("a"), True)]) #end. { a }. b :- a. clingo-5.2.2/app/clingo/tests/python/assumptions1.sol000066400000000000000000000000201320011352300226540ustar00rootroot00000000000000Step: 1 a b SAT clingo-5.2.2/app/clingo/tests/python/assumptions2.lp000066400000000000000000000002621320011352300225030ustar00rootroot00000000000000#script (python) import sys from clingo import Function def main(prg): prg.ground([("base", [])]) prg.solve(assumptions=[(Function("b"), True)]) #end. { a }. b :- a. clingo-5.2.2/app/clingo/tests/python/assumptions2.sol000066400000000000000000000000201320011352300226550ustar00rootroot00000000000000Step: 1 a b SAT clingo-5.2.2/app/clingo/tests/python/assumptions3.lp000066400000000000000000000004711320011352300225060ustar00rootroot00000000000000#script (python) import sys from clingo import Function def main(prg): prg.ground([("base", [])]) prg.solve(assumptions=[(Function("a"), True), (Function("b"), False), (Function("d"), True)]) prg.solve(assumptions=[(Function("a"), False), (Function("c"), True)]) #end. #external d. { a; b; c }. clingo-5.2.2/app/clingo/tests/python/assumptions3.sol000066400000000000000000000000321320011352300226610ustar00rootroot00000000000000Step: 1 Step: 2 b c c SAT clingo-5.2.2/app/clingo/tests/python/assumptions4.lp000066400000000000000000000006261320011352300225110ustar00rootroot00000000000000#script (python) import sys from clingo import Function def main(prg): prg.ground([("base", [])]) prg.solve(assumptions=[(Function("a"), True)]) with prg.solve(assumptions=[(Function("a"), True)], async=True) as handle: handle.get() with prg.solve(assumptions=[(Function("a"), True)], yield_=True) as handle: for model in handle: pass #end. { a }. b :- a. clingo-5.2.2/app/clingo/tests/python/assumptions4.sol000066400000000000000000000000501320011352300226620ustar00rootroot00000000000000Step: 1 a b Step: 2 a b Step: 3 a b SAT clingo-5.2.2/app/clingo/tests/python/ast.lp000066400000000000000000000150671320011352300206340ustar00rootroot00000000000000#script (python) import clingo import clingo.ast as ast def get_type(x): return x.atom.type if x.type == ast.ASTType.Literal else x.type def add(r): return [(n, clingo.Function("ok" if str(x) == s and get_type(x) == t else "fail")) for n, (x, s, t) in zip(range(len(r)), r)] def test(): loc = None id_i = ast.Id(loc, "i") trm_v = ast.Variable(loc, "X") trm_s = ast.Symbol(loc, 2) trm_u = ast.UnaryOperation(loc, ast.UnaryOperator.Absolute, trm_v) trm_b = ast.BinaryOperation(loc, ast.BinaryOperator.Multiplication, trm_u, trm_s) trm_f = ast.Function(loc, "f", [trm_v,trm_s,trm_u,trm_b], True) trm_p = ast.Pool(loc, [trm_s,trm_v]) csp_p = ast.CSPProduct(loc, trm_s, trm_v) csp_s = ast.CSPSum(loc, [csp_p, csp_p]) csp_g = ast.CSPGuard(ast.ComparisonOperator.Equal, csp_s) lit_b = ast.BooleanConstant(True); lit_s = ast.Literal(loc, ast.Sign.Negation, ast.SymbolicAtom(ast.Function(loc, "p", [trm_s], False))); lit_t = ast.Literal(loc, ast.Sign.NoSign, ast.SymbolicAtom(ast.Function(loc, "q", [trm_s], False))); lit_r = ast.Comparison(ast.ComparisonOperator.LessThan, trm_v, trm_s) lit_c = ast.CSPLiteral(loc, csp_s, [csp_g]) lit_l = ast.ConditionalLiteral(loc, lit_s, [lit_b]) agg_g = ast.AggregateGuard(ast.ComparisonOperator.NotEqual, trm_s) agg_l = ast.Literal(loc, ast.Sign.Negation, ast.Aggregate(loc, None, [lit_l], agg_g)) agg_e = ast.BodyAggregateElement([trm_s, trm_v], [lit_b]) agg_t = ast.Literal(loc, ast.Sign.DoubleNegation, ast.BodyAggregate(loc, agg_g, ast.AggregateFunction.Sum, [agg_e], None)) agg_m = ast.Aggregate(loc, agg_g, [lit_l], agg_g) agg_f = ast.HeadAggregateElement([trm_s, trm_v], lit_l) agg_u = ast.HeadAggregate(loc, agg_g, ast.AggregateFunction.Sum, [agg_f], None) agg_d = ast.Disjunction(loc, [lit_l, lit_l]) agg_h = ast.DisjointElement(loc, [trm_v, trm_s], csp_s, [lit_b, lit_s]) agg_i = ast.Literal(loc, ast.Sign.DoubleNegation, ast.Disjoint(loc, [agg_h])) tha_s = ast.TheorySequence(loc, ast.TheorySequenceType.Set, [trm_v, trm_s]) tha_f = ast.TheoryFunction(loc, "f", [tha_s, trm_s]) tha_e = ast.TheoryUnparsedTermElement(["+", "-"], trm_s) tha_u = ast.TheoryUnparsedTerm(loc, [tha_e, tha_e]) tha_g = ast.TheoryGuard("!!", trm_s) tha_h = ast.TheoryAtomElement([trm_v, trm_s], [lit_b]) tha_a = ast.TheoryAtom(loc, trm_v, [tha_h], tha_g) thd_o = ast.TheoryOperatorDefinition(loc, "-", 7, ast.TheoryOperatorType.Unary) thd_t = ast.TheoryTermDefinition(loc, "t", [thd_o]) thd_g = ast.TheoryGuardDefinition([">", "<"], "t") thd_a = ast.TheoryAtomDefinition(loc, ast.TheoryAtomType.Any, "p", 2, "t", thd_g) thd_d = ast.TheoryDefinition(loc, "x", [thd_t], [thd_a]) stm_r = ast.Rule(loc, lit_s, [lit_s, lit_t]) stm_c = ast.Definition(loc, "x", trm_s, True) stm_s = ast.ShowSignature(loc, "x", 2, True, True) stm_t = ast.ShowTerm(loc, trm_s, [lit_s], True) stm_m = ast.Minimize(loc, trm_s, trm_s, [trm_v], [lit_s]) stm_p = ast.Script(loc, ast.ScriptType.Python, "blub!") stm_q = ast.Program(loc, "p", [id_i]) stm_e = ast.External(loc, trm_s, [lit_s]) stm_a = ast.Edge(loc, trm_s, trm_s, [lit_s]) stm_h = ast.Heuristic(loc, trm_s, [lit_s], trm_s, trm_s, trm_s) stm_x = ast.ProjectAtom(loc, trm_s, [lit_s]) stm_y = ast.ProjectSignature(loc, "p", 2, True) return add([ (id_i, "i", ast.ASTType.Id), (trm_v, "X", ast.ASTType.Variable), (trm_s, "2", ast.ASTType.Symbol), (trm_u, "|X|", ast.ASTType.UnaryOperation), (trm_b, "(|X|*2)", ast.ASTType.BinaryOperation), (trm_f, "@f(X,2,|X|,(|X|*2))", ast.ASTType.Function), (trm_p, "(2;X)", ast.ASTType.Pool), (csp_p, "2$*$X", ast.ASTType.CSPProduct), (csp_s, "2$*$X$+2$*$X", ast.ASTType.CSPSum), (csp_g, "$=2$*$X$+2$*$X", ast.ASTType.CSPGuard), (lit_b, "#true", ast.ASTType.BooleanConstant), (lit_s, "not p(2)", ast.ASTType.SymbolicAtom), (lit_r, "X<2", ast.ASTType.Comparison), (lit_c, "2$*$X$+2$*$X$=2$*$X$+2$*$X", ast.ASTType.CSPLiteral), (lit_l, "not p(2) : #true", ast.ASTType.ConditionalLiteral), (agg_g, "AggregateGuard(!=, 2)", ast.ASTType.AggregateGuard), (agg_l, "not { not p(2) : #true } != 2", ast.ASTType.Aggregate), (agg_e, "2,X : #true", ast.ASTType.BodyAggregateElement), (agg_t, "not not 2 != #sum { 2,X : #true }", ast.ASTType.BodyAggregate), (agg_m, "2 != { not p(2) : #true } != 2", ast.ASTType.Aggregate), (agg_f, "2,X : not p(2) : #true", ast.ASTType.HeadAggregateElement), (agg_u, "2 != #sum { 2,X : not p(2) : #true }", ast.ASTType.HeadAggregate), (agg_d, "not p(2) : #true; not p(2) : #true", ast.ASTType.Disjunction), (agg_h, "X,2 : 2$*$X$+2$*$X : #true,not p(2)", ast.ASTType.DisjointElement), (agg_i, "not not #disjoint { X,2 : 2$*$X$+2$*$X : #true,not p(2) }", ast.ASTType.Disjoint), (tha_s, "{X,2}", ast.ASTType.TheorySequence), (tha_f, "f({X,2},2)", ast.ASTType.TheoryFunction), (tha_e, "+ - 2", ast.ASTType.TheoryUnparsedTermElement), (tha_u, "(+ - 2 + - 2)", ast.ASTType.TheoryUnparsedTerm), (tha_g, "!! 2", ast.ASTType.TheoryGuard), (tha_h, "X,2 : #true", ast.ASTType.TheoryAtomElement), (tha_a, "&X { X,2 : #true } !! 2", ast.ASTType.TheoryAtom), (thd_o, "- : 7, unary", ast.ASTType.TheoryOperatorDefinition), (thd_t, "t {\n - : 7, unary\n}", ast.ASTType.TheoryTermDefinition), (thd_g, "{ >, < }, t", ast.ASTType.TheoryGuardDefinition), (thd_a, "&p/2 : t, { >, < }, t, any", ast.ASTType.TheoryAtomDefinition), (thd_d, "#theory x {\n t {\n - : 7, unary\n };\n &p/2 : t, { >, < }, t, any\n}.", ast.ASTType.TheoryDefinition), (stm_r, "not p(2) :- not p(2); q(2).", ast.ASTType.Rule), (stm_c, "#const x = 2. [default]", ast.ASTType.Definition), (stm_s, "#show $x/2.", ast.ASTType.ShowSignature), (stm_t, "#show $2 : not p(2).", ast.ASTType.ShowTerm), (stm_m, ":~ not p(2). [2@2,X]", ast.ASTType.Minimize), (stm_p, "blub!", ast.ASTType.Script), (stm_q, "#program p(i).", ast.ASTType.Program), (stm_e, "#external 2 : not p(2).", ast.ASTType.External), (stm_a, "#edge (2,2) : not p(2).", ast.ASTType.Edge), (stm_h, "#heuristic 2 : not p(2). [2@2,2]", ast.ASTType.Heuristic), (stm_x, "#project 2 : not p(2).", ast.ASTType.ProjectAtom), (stm_y, "#project p/2.", ast.ASTType.ProjectSignature), ]) def main(prg): prg.ground([("base", [])]) prg.solve() #end. test(N,R) :- (N,R) = @test(). clingo-5.2.2/app/clingo/tests/python/ast.sol000066400000000000000000000011161320011352300210040ustar00rootroot00000000000000Step: 1 test(0,ok) test(1,ok) test(10,ok) test(11,ok) test(12,ok) test(13,ok) test(14,ok) test(15,ok) test(16,ok) test(17,ok) test(18,ok) test(19,ok) test(2,ok) test(20,ok) test(21,ok) test(22,ok) test(23,ok) test(24,ok) test(25,ok) test(26,ok) test(27,ok) test(28,ok) test(29,ok) test(3,ok) test(30,ok) test(31,ok) test(32,ok) test(33,ok) test(34,ok) test(35,ok) test(36,ok) test(37,ok) test(38,ok) test(39,ok) test(4,ok) test(40,ok) test(41,ok) test(42,ok) test(43,ok) test(44,ok) test(45,ok) test(46,ok) test(47,ok) test(48,ok) test(5,ok) test(6,ok) test(7,ok) test(8,ok) test(9,ok) SAT clingo-5.2.2/app/clingo/tests/python/ast2.lp000066400000000000000000000107461320011352300207150ustar00rootroot00000000000000#script (python) import clingo def parse(s): ret = [] clingo.parse_program(s, lambda stm: ret.append(str(stm))) return ret[1:] def check(l): ret = [] for n, (p, r) in zip(range(len(l)), l): ret.append((n, clingo.Function("ok" if parse(p) == r else "fail"))) return ret def stm(): return check([ ("a.", ["a."]), ("a:-b.", ["a :- b."]), ("#const a=10.", ["#const a = 10. [default]"]), ("#show a/1.", ["#show a/1."]), ("#show $a/1.", ["#show $a/1."]), ("#show a : b.", ["#show a : b."]), ("#show $a : b.", ["#show $a : b."]), ("#minimize{ 1:b }.", [":~ b. [1@0]"]), ("#script (python) 42 #" + "end.", ["#script (python) 42 #" + "end."]), ("#program p(k).", ["#program p(k)."]), ("#external p(k).", ["#external p(k)."]), ("#external p(k) : a, b.", ["#external p(k) : a; b."]), ("#edge (u,v) : a, b.", ["#edge (u,v) : a; b."]), ("#heuristic a : b, c. [L@P,level]", ["#heuristic a : b; c. [L@P,level]"]), ("#project a : b.", ["#project a : b."]), ("#project a/2.", ["#project a/2."]), ("#theory x {}.", ["#theory x {\n}."]), ]) def thd(): return check([ ("#theory x { t { ++ : 1, unary } }.", ["#theory x {\n t {\n ++ : 1, unary\n }\n}."]), ("#theory x { &a/0 : t, any }.", ["#theory x {\n &a/0 : t, any\n}."]), ("#theory x { &a/0 : t, {+, -}, u, any }.", ["#theory x {\n &a/0 : t, { +, - }, u, any\n}."]), ]) def bdl(): return check([ (":-a.", ["#false :- a."]), (":-not a.", ["#false :- not a."]), (":-not not a.", ["#false :- not not a."]), (":-a:b.", ["#false :- a : b."]), (":-a:b,c;d.", ["#false :- a : b, c; d."]), (":-1{a:b,c;e}2.", ["#false :- 1 <= { a : b, c; e : } <= 2."]), (":-{a:b,c;e}2.", ["#false :- 2 >= { a : b, c; e : }."]), (":-1#min{1,2:b,c;1:e}2.", ["#false :- 1 <= #min { 1,2 : b, c; 1 : e } <= 2."]), (":-&p { 1 : a,b; 2 : c }.", ["#false :- &p { 1 : a,b; 2 : c }."]), (":-#disjoint {1,2:$x:a,b}.", ["#false :- #disjoint { 1,2 : 1$*$x : a,b }."]), ]) def hdl(): return check([ ("a.", ["a."]), ("a:b.", ["a : b."]), ("a:b,c;d.", ["d : ; a : b, c."]), ("1{a:b,c;e}2.", ["1 <= { a : b, c; e : } <= 2."]), ("{a:b,c;e}2.", ["2 >= { a : b, c; e : }."]), ("1#min{1,2:h:b,c;1:e}2.", ["1 <= #min { 1,2 : h : b, c; 1 : e : } <= 2."]), ("&p { 1 : a,b; 2 : c }.", ["&p { 1 : a,b; 2 : c }."]), ("&p { 1 : a,b; 2 : c } ** 33.", ["&p { 1 : a,b; 2 : c } ** 33."]), ]) def lit(): return check([ ("#true.", ["#true."]), ("#false.", ["#false."]), ("a.", ["a."]), ("not a.", ["not a."]), ("not not a.", ["not not a."]), ("1 != 3.", ["1!=3."]), ("1 $< 2 $< 3.", ["1$<2$<3."]), ("1 $< 2 $< 3.", ["1$<2$<3."]), ]) def trm(): return check([ ("p(a).", ["p(a)."]), ("p(X).", ["p(X)."]), ("p(-a).", ["p(-a)."]), ("p(~a).", ["p(~a)."]), ("p(|a|).", ["p(|a|)."]), ("p((a+b)).", ["p((a+b))."]), ("p((a-b)).", ["p((a-b))."]), ("p((a*b)).", ["p((a*b))."]), ("p((a/b)).", ["p((a/b))."]), ("p((a\\b)).", ["p((a\\b))."]), ("p((a?b)).", ["p((a?b))."]), ("p((a^b)).", ["p((a^b))."]), ("p(a..b).", ["p((a..b))."]), ("p((),(1,),f(),f(1,2)).", ["p((),(1,),f,f(1,2))."]), ("p(a;b).", ["(p(a);p(b))."]), ("p((a,;b)).", ["p(((a,);b))."]), ("1 $+ 3 $* $x $+ 7 $< 2 $< 3.", ["1$+3$*$x$+7$<2$<3."]), ]) def tht(): return check([ ("&p{ } !! a.", ["&p { } !! a."]), ("&p{ } !! X.", ["&p { } !! X."]), ("&p{ } !! [].", ["&p { } !! []."]), ("&p{ } !! [1].", ["&p { } !! [1]."]), ("&p{ } !! [1,2].", ["&p { } !! [1,2]."]), ("&p{ } !! ().", ["&p { } !! ()."]), ("&p{ } !! (a).", ["&p { } !! a."]), ("&p{ } !! (a,).", ["&p { } !! (a,)."]), ("&p{ } !! {}.", ["&p { } !! {}."]), ("&p{ } !! f().", ["&p { } !! f."]), ("&p{ } !! f(a,1).", ["&p { } !! f(a,1)."]), ("&p{ } !! 1 + (x + y * z).", ["&p { } !! (1 + (x + y * z))."]), ]) def main(prg): prg.ground([("base", [])]) prg.solve() #end. stm(N,R) :- (N,R) = @stm(). thd(N,R) :- (N,R) = @thd(). bdl(N,R) :- (N,R) = @bdl(). hdl(N,R) :- (N,R) = @hdl(). lit(N,R) :- (N,R) = @lit(). trm(N,R) :- (N,R) = @trm(). tht(N,R) :- (N,R) = @tht(). clingo-5.2.2/app/clingo/tests/python/ast2.sol000066400000000000000000000014121320011352300210650ustar00rootroot00000000000000Step: 1 bdl(0,ok) bdl(1,ok) bdl(2,ok) bdl(3,ok) bdl(4,ok) bdl(5,ok) bdl(6,ok) bdl(7,ok) bdl(8,ok) bdl(9,ok) hdl(0,ok) hdl(1,ok) hdl(2,ok) hdl(3,ok) hdl(4,ok) hdl(5,ok) hdl(6,ok) hdl(7,ok) lit(0,ok) lit(1,ok) lit(2,ok) lit(3,ok) lit(4,ok) lit(5,ok) lit(6,ok) lit(7,ok) stm(0,ok) stm(1,ok) stm(10,ok) stm(11,ok) stm(12,ok) stm(13,ok) stm(14,ok) stm(15,ok) stm(16,ok) stm(2,ok) stm(3,ok) stm(4,ok) stm(5,ok) stm(6,ok) stm(7,ok) stm(8,ok) stm(9,ok) thd(0,ok) thd(1,ok) thd(2,ok) tht(0,ok) tht(1,ok) tht(10,ok) tht(11,ok) tht(2,ok) tht(3,ok) tht(4,ok) tht(5,ok) tht(6,ok) tht(7,ok) tht(8,ok) tht(9,ok) trm(0,ok) trm(1,ok) trm(10,ok) trm(11,ok) trm(12,ok) trm(13,ok) trm(14,ok) trm(15,ok) trm(16,ok) trm(2,ok) trm(3,ok) trm(4,ok) trm(5,ok) trm(6,ok) trm(7,ok) trm(8,ok) trm(9,ok) SAT clingo-5.2.2/app/clingo/tests/python/ast3.lp000066400000000000000000000104361320011352300207120ustar00rootroot00000000000000#script (python) import clingo def solve(s): prg = clingo.Control(["0", "-Wno-operation-undefined"]) with prg.builder() as b: clingo.parse_program(s, lambda stm: b.add(stm)) prg.ground([("base", [])]) ret = [] prg.solve(on_model=lambda m: ret.append(sorted(m.symbols(shown=True)))) return str(sorted(ret)) def parse(s): prg = clingo.Control([]) with prg.builder() as b: clingo.parse_program(s, lambda stm: b.add(stm)) prg.ground([("base", [])]) return str([x for x in prg.theory_atoms]) def check(l, t = "", s=solve): ret = [] for n, (p, r) in zip(range(len(l)), l): ret.append((n, clingo.Function("ok" if s(p+t) == r else "fail"))) return ret def stm(): return check([ ("a.", "[[a]]"), ("a. c. b :- a, c.", "[[a, b, c]]"), ("#const a=10. p(a).", "[[p(10)]]"), ("a. b. #show a/0.", "[[a]]"), ("$a$=1. $b$=2. #show $a/0.", "[[$(a,1)]]"), ("a. #show b : a.", "[[a, b]]"), ("$a$=1. $b$=2. #show. #show $a.", "[[$(a,1)]]"), ("#minimize{ 1:b; 2:a }. {a;b}. :- not a, not b.", "[[b]]"), # NOTE: atm the script code is not evaluated... ("#script (python) def x() return 32; end #"+ "end. p(@x()).", "[[]]"), ("#edge (u,v) : a. #edge (v,u) : b. {a;b}.", "[[], [a], [b]]"), ("#theory x {}.", "[[]]"), ("#external a.", "[[]]"), ("#heuristic a : b, c. [1@2,level] b. c.", "[[b, c]]"), ("#project a.", "[[]]"), ("#project a/0.", "[[]]"), ]) def bdl(): return check([ ("{a}. :-a.", "[[]]"), ("{a}. :-not a.", "[[a]]"), ("{a}. :-not not a.", "[[]]"), (":-a:b. 0{a; b}0.", "[]"), (":-0{a:b;c}1. {a;b;c}.", "[[a, b, c]]"), (":-0#min{1,2:a,b;2:c}2. {a;b;c}.", "[[], [a], [b]]"), ("1 $<= $x $<= 2. 1 $<= $y $<= 2. :- #disjoint {1:$x; 2:$y}.", "[[$(x,1), $(y,1)], [$(x,2), $(y,2)]]"), ]) def hdl(): return check([ ("a.", "[[a]]"), ("not a. a :- #false.", "[[]]"), ("not not a. a :- #false.", "[]"), ("a:b;c.{b}.", "[[a, b], [b, c], [c]]"), ("1{a:b;b}2.", "[[a, b], [b]]"), ("#min{1,2:a;2:c}1.", "[[a], [a, c]]"), ]) def lit(): return check([ ("a.", "[[a]]"), ("1=1.", "[[]]"), ("1!=1.", "[]"), ("#true.", "[[]]"), ("#false.", "[]"), ("1 $< 2 $< 3.", "[[]]"), ("2 $< 3 $< 1.", "[]"), ]) def trm(): return check([ ("p(a).", "[[p(a)]]"), ("p(X) :- X=a.", "[[p(a)]]"), ("p(-1).", "[[p(-1)]]"), ("p(|1|).", "[[p(1)]]"), ("p((3+2)).", "[[p(5)]]"), ("p((3-2)).", "[[p(1)]]"), ("p((3*2)).", "[[p(6)]]"), ("p((7/2)).", "[[p(3)]]"), ("p((7\\2)).", "[[p(1)]]"), ("p((7?2)).", "[[p(7)]]"), ("p((7^2)).", "[[p(5)]]"), ("p(3..3).", "[[p(3)]]"), ("p(a;b).", "[[p(a), p(b)]]"), ("p((),(1,),f(),f(1,2)).", "[[p((),(1,),f,f(1,2))]]"), ("p((a,;b)).", "[[p(b), p((a,))]]"), ("12 $< 1 $+ 3 $* $x $+ 7 $< 17. 0 $<= x $<= 4.", "[[$(x,2)]]"), ]) def tht(): theory = ''' #theory x { t { * : 1, binary, left; ^ : 2, binary, right; - : 3, unary }; &a/0 : t, directive; &b/0 : t, {=}, t, any }. ''' return check([ ("&a{}.", "[&a{}]"), ("&a{1,2,3:a,b}. {a;b}.", "[&a{1,2,3: a,b}]"), ("&b{} = a.", "[&b{}=a]"), ("&b{} = X:-X=1.", "[&b{}=1]"), ("&b{} = [].", "[&b{}=[]]"), ("&b{} = [1].", "[&b{}=[1]]"), ("&b{} = [1,2].", "[&b{}=[1,2]]"), ("&b{} = ().", "[&b{}=()]"), ("&b{} = (a).", "[&b{}=a]"), ("&b{} = (a,).", "[&b{}=(a,)]"), ("&b{} = {}.", "[&b{}={}]"), ("&b{} = f().", "[&b{}=f()]"), ("&b{} = f(a,1).", "[&b{}=f(a,1)]"), ("&b{} = a*x.", "[&b{}=(a*x)]"), ("&b{} = -a*x*y^z^u.", "[&b{}=(((-a)*x)*(y^(z^u)))]"), ("&b{} = -(a*x*y^z^u).", "[&b{}=(-((a*x)*(y^(z^u))))]"), ], theory, parse) def main(prg): prg.ground([("base", [])]) prg.solve() #end. stm(N,R) :- (N,R) = @stm(). bdl(N,R) :- (N,R) = @bdl(). hdl(N,R) :- (N,R) = @hdl(). lit(N,R) :- (N,R) = @lit(). trm(N,R) :- (N,R) = @trm(). tht(N,R) :- (N,R) = @tht(). clingo-5.2.2/app/clingo/tests/python/ast3.sol000066400000000000000000000012731320011352300210730ustar00rootroot00000000000000Step: 1 bdl(0,ok) bdl(1,ok) bdl(2,ok) bdl(3,ok) bdl(4,ok) bdl(5,ok) bdl(6,ok) hdl(0,ok) hdl(1,ok) hdl(2,ok) hdl(3,ok) hdl(4,ok) hdl(5,ok) lit(0,ok) lit(1,ok) lit(2,ok) lit(3,ok) lit(4,ok) lit(5,ok) lit(6,ok) stm(0,ok) stm(1,ok) stm(10,ok) stm(11,ok) stm(12,ok) stm(13,ok) stm(14,ok) stm(2,ok) stm(3,ok) stm(4,ok) stm(5,ok) stm(6,ok) stm(7,ok) stm(8,ok) stm(9,ok) tht(0,ok) tht(1,ok) tht(10,ok) tht(11,ok) tht(12,ok) tht(13,ok) tht(14,ok) tht(15,ok) tht(2,ok) tht(3,ok) tht(4,ok) tht(5,ok) tht(6,ok) tht(7,ok) tht(8,ok) tht(9,ok) trm(0,ok) trm(1,ok) trm(10,ok) trm(11,ok) trm(12,ok) trm(13,ok) trm(14,ok) trm(15,ok) trm(2,ok) trm(3,ok) trm(4,ok) trm(5,ok) trm(6,ok) trm(7,ok) trm(8,ok) trm(9,ok) SAT clingo-5.2.2/app/clingo/tests/python/blocksworld1.lp000066400000000000000000000160171320011352300224470ustar00rootroot00000000000000% show instances of selected predicates only #show. % output stack representation #show order/4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for generating states providing relative block positions, using % % - parameter k for block number % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program state(k,t). % a block's scope includes the table (labeled 0) and blocks with smaller numbers scope(k,0,t). scope(k,I,t) :- scope(I,0,t), I < k. % order(1,k,I,t) provides the closest block I in scope above k, if any at time t #count{ I : order(1,k,I,t) : scope(k,I,t), 0 < I } 1. % order(-1,k,I,t) provides the closest block/table I in scope below k at time t 1 #count{ I : order(-1,k,I,t) : scope(k,I,t) } 1. % trace order/4 to derive transitive closure of objects in scope above/below k trans(D,k,I,t) :- order(D,k,I,t). trans(D,k,I,t) :- trans(D,k,J,t), order(D,J,I,t). trans(D,k,J,t) :- trans(D,k,I,t), order(-D,J,I,t), scope(k,J,t). % state constraint that the table is transitively below block k (redundant) :- not trans(-1,k,0,t). % state constraint propagating immediate above/below relationships :- order(-1,k,I,t), order(1,k,J,t), not order(-1,J,I,t), not order(1,I,J,t). % state constraint aligning immediate and transitive above/below relationships :- order(-D,k,J,t), order(D,J,I,t), not trans(D,k,I,t), 0 < I. % D=-1 redundant % state constraint directing transitive above/below relationships on convergence :- order(D,k,I,t), order(D,J,I,t), not trans(-D,k,J,t), scope(k,J,t), 0 < I. % rules below are volatile with life span 1 % #program volatile(k,t). #external scope(k,0,t+1). % goal state conditions :- goal_above(k,I), not trans(-1,k,I,t), not scope(k,0,t+1). :- goal_below(k,I), not trans(1,k,I,t), not scope(k,0,t+1). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for generating moves having a block as object and target, using % % - parameter k for block number % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program move(k,t). % external atoms indicating involvement of blocks with greater numbers in move #external change(-1,k,I,t) : scope(I,0,t), I <= k. #external change( 1,k,I,t) : scope(I,0,t-1), I <= k. #external change(-1,k,t). #external change( 1,k,t). % output object and target block of move #show object(k,t) : object(k,t). #show target(k,t) : target(k,t). % propagate role as move object (via D=1) or target (via D=-1) to smaller block change(1,k-1,I,t) :- order(1,k,I,t), scope(I,0,t-1), not order(1,k,I,t-1). change(D,k-1,I,t) :- order(D,k,I,t-(D+|D|)/2), scope(k,0,t-1), 0 < I, not order(D,k,I,t+(D-|D|)/2). change(D,k-1,I,t) :- change(D,k,I,t), I < k. % , scope(I,0,t-(D+|D|)/2). % combine possibilities how move affects block as object (D=1) or target (D=-1) affect(-D,k,t) :- order(D,k,I,t+(D-|D|)/2), scope(I,0,t-1) : D == 1; not order(D,k,I,t-(D+|D|)/2). affect( D,k,t) :- change(D,k,k,t). % , scope(k,0,t-(D+|D|)/2). % propagate existence of some move object or target to smaller blocks and table change(D,k-1,t) :- affect(D,k,t). change(D,k-1,t) :- change(D,k,t). % derive moved object and corresponding target object(k,t) :- affect(1,k,t). target(k,t) :- affect(-1,k,t), not change(-1,k,t). % moved object must be unique :- object(k,t), change(1,k,t). % moved object must be free :- object(k,t), order(1,k,_,t-1). :- object(I,t), order(-1,k,I,t-1). % moved object must not go under (unmoved) pre-existing block :- object(k,t), order(1,k,I,t), scope(I,0,t-1). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for deriving target table from move without target block, using % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program table(t). % external atoms indicating involvement of blocks with greater numbers in move #external change(-1,0,t). #external change( 1,0,t). % output target table of move #show target(0,t) : target(0,t). % derive table as target of move target(0,t) :- change(1,0,t), not change(-1,0,t). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % program part for establishing consistent initial position for a block, using % % - parameter k for block number % % - parameter t for step number at instantiation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #program init(k,t). % no appearance under unmoved pre-existing block :- order(1,k,I,t), scope(I,0,t-1), not object(I,t). % initial state conditions :- init_above(k,I), not trans(-1,k,I,t). :- init_below(k,I), not trans(1,k,I,t). % clingo-4-banane clingo-4-blocksworld.lp clingo-4-main.lp 0 #script (python) def main(prg): parts = [] parts.append(("init", [1,0])) parts.append(("state", [1,0])) prg.ground(parts) prg.solve() parts = [] parts.append(("base_2", [])) parts.append(("init", [2,0])) parts.append(("state", [2,0])) for i in range(1, 3): parts.append(("table", [i])) for j in range(1, 3): parts.append(("state", [j,i])) parts.append(("move", [j,i])) prg.ground(parts) prg.solve() parts = [] parts.append(("base_3", [])) parts.append(("init", [3,0])) parts.append(("state", [3,0])) for i in range(1, 4): parts.append(("state", [3,i])) parts.append(("move", [3,i])) for j in range(1, 3): parts.append(("state", [j,3])) parts.append(("move", [j,3])) parts.append(("table", [3])) prg.ground(parts) prg.solve() parts = [] parts.append(("base_4", [])) parts.append(("init", [4,0])) parts.append(("state", [4,0])) for i in range(1, 5): parts.append(("state", [4,i])) parts.append(("move", [4,i])) for j in range(1, 4): parts.append(("state", [j,4])) parts.append(("move", [j,4])) parts.append(("table", [4])) prg.ground(parts) prg.solve() parts = [] parts.append(("base_5", [])) parts.append(("init", [5,1])) for i in range(1, 8): parts.append(("state", [5,i])) parts.append(("move", [5,i])) for i in range(5, 8): parts.append(("table", [i])) for j in range(1, 5): parts.append(("state", [j,i])) parts.append(("move", [j,i])) prg.ground(parts) prg.solve() #end. #program base_2. init_above(2,1). goal_below(2,1). #program base_3. init_above(3,2). goal_below(3,1). #program base_4. init_above(4,2). init_below(4,3). goal_above(4,3). goal_below(4,1). #program base_5. init_above(5,1). init_below(5,3). goal_above(5,2). clingo-5.2.2/app/clingo/tests/python/blocksworld1.sol000066400000000000000000000056041320011352300226310ustar00rootroot00000000000000Step: 1 order(-1,1,0,0) Step: 2 object(1,2) object(2,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,2,0,1) order(-1,2,0,2) order(-1,2,1,0) order(1,2,1,2) target(0,1) target(2,2) Step: 3 object(1,3) object(2,2) object(3,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,2,0,2) order(-1,2,0,3) order(-1,2,1,0) order(-1,2,1,1) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,2,0) order(1,2,1,3) order(1,3,2,2) order(1,3,2,3) target(0,1) target(2,3) target(3,2) Step: 4 object(1,4) object(2,3) object(3,1) object(4,2) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,2,0,3) order(-1,2,0,4) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,2,0) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,3,2) order(-1,4,3,3) order(-1,4,3,4) order(1,2,1,4) order(1,3,2,3) order(1,3,2,4) order(1,4,2,3) order(1,4,2,4) order(1,4,3,0) target(0,1) target(2,4) target(3,2) target(4,3) Step: 5 object(1,6) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,7) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,0,6) order(-1,5,1,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,6) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,3,1) target(0,2) target(0,3) target(1,7) target(2,6) target(3,4) target(4,5) target(5,1) object(1,7) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,6) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,2,6) order(-1,5,2,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,1,7) order(1,5,3,1) target(0,2) target(0,3) target(2,6) target(3,4) target(4,5) target(5,1) target(5,7) SAT clingo-5.2.2/app/clingo/tests/python/cancel.lp000066400000000000000000000007371320011352300212700ustar00rootroot00000000000000#script (python) import clingo def main(prg): prg.ground([("pigeon", [])]) for i in range(0,2): prg.assign_external(clingo.Function("p"), True) prg.solve() prg.assign_external(clingo.Function("p"), False) with prg.solve(async=True) as handle: handle.wait(0.01) handle.cancel() #end. #const n = 190. #program pigeon. #external p. 1 { p(X); q(X) } 1 :- X = 1..n, not p. :- not n+1 { p(1..n); q(1..n) }, not p. clingo-5.2.2/app/clingo/tests/python/cancel.sol000066400000000000000000000000541320011352300214420ustar00rootroot00000000000000Step: 1 p Step: 2 Step: 3 p Step: 4 UNKNOWN clingo-5.2.2/app/clingo/tests/python/check-py.lp000066400000000000000000000017721320011352300215460ustar00rootroot00000000000000#script (python) import clingo class Propagator: def __init__(self): self.__lits = set() def init(self, init): for atom in init.symbolic_atoms: sym = atom.symbol if sym.name == "p" and len(sym.arguments) == 1: self.__lits.add(init.solver_literal(atom.literal)) assert(init.check_mode == clingo.PropagatorCheckMode.Total) assert(init.check_mode != clingo.PropagatorCheckMode.Fixpoint) assert(init.check_mode != clingo.PropagatorCheckMode.Off) init.check_mode = clingo.PropagatorCheckMode.Fixpoint assert(init.check_mode == clingo.PropagatorCheckMode.Fixpoint) def check(self, ctl): # assert(not ctl.assignment.is_total) for lit in self.__lits: if ctl.assignment.value(lit) is None: ctl.add_clause([lit]) break def main(prg): p = Propagator() prg.register_propagator(p) prg.ground([("base", [])]) prg.solve() #end. { p(1..10) }. clingo-5.2.2/app/clingo/tests/python/check-py.sol000066400000000000000000000000771320011352300217250ustar00rootroot00000000000000Step: 1 p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9) SAT clingo-5.2.2/app/clingo/tests/python/cover-py.lp000066400000000000000000000044211320011352300216010ustar00rootroot00000000000000#script (python) import clingo import sys class State: def __init__(self): self.leaves = {} self.last = None def fix(self, k): return self.leaves.get(k.number-1, []) def on_model(self, m): self.last = m.symbols(atoms=True) for atom in self.last: if atom.name == "leaf": args = atom.arguments self.leaves[args[0]] = args[1] def prepare_instance(self, k): edges = [] cover = [] vertices = set() for atom in self.last: if atom.name == "edge": args = atom.arguments if args[0].number == k-1: edges.append((args[1], args[2])) vertices.add(args[1]) vertices.add(args[2]) if atom.name == "cover": cover.append(atom.arguments[1]) vertices = list(vertices) setattr(self, "edge", lambda: edges) setattr(self, "cover", lambda: cover) setattr(self, "vertex", lambda: vertices) def run(self, prg): pre = clingo.Control() pre.add("base", [], """ edge(a,(b;c)). edge(b,(c;d)). edge(d,e). edge(e,f). edge(x,(a;c)). % edge to keep something to solve edge(X,Y) :- edge(Y,X). vertex(X) :- edge(X,Y;Y,X). edge(0,X,Y) :- edge(X,Y). """) pre.add("step", ["k"], """ :- not leaf(k-1,@fix(k)). 1 { leaf(k,X) : vertex(X) } 1. cover(k,X) :- edge(k-1,X,Y), leaf(k,Y). edge(k,X,Y) :- edge(k-1,X,Y), not cover(k,X), not cover(k,Y). :- edge(k-1,X,Y), leaf(k,Y), edge(k-1,Y,Z), X < Z. :- leaf(k,Y), not edge(k-1,_,Y). """) pre.ground([("base", [])]) ret = pre.solve(on_model = self.on_model) k = 0 while ret.satisfiable is True: k = k + 1 pre.cleanup() pre.ground([("step", [k])], self) ret = pre.solve(on_model = self.on_model) self.prepare_instance(k) prg.add("base", [], """ vertex(X) :- X = @vertex(). edge(X,Y) :- (X,Y) = @edge(). cover(X) :- X = @cover(). { cover(X) : vertex(X) }. :- edge(X,Y), not cover(X), not cover(Y). %#minimize { 1,X : cover(X) }. #show cover/1. """) prg.ground([("base", [])], self) prg.solve() def main(prg): s = State() s.run(prg) #end. clingo-5.2.2/app/clingo/tests/python/cover-py.sol000066400000000000000000000002451320011352300217630ustar00rootroot00000000000000Step: 1 cover(a) cover(b) cover(c) cover(e) cover(a) cover(b) cover(c) cover(e) cover(x) cover(a) cover(b) cover(e) cover(x) cover(b) cover(c) cover(e) cover(x) SAT clingo-5.2.2/app/clingo/tests/python/domain.lp000066400000000000000000000016721320011352300213110ustar00rootroot00000000000000p(1). { p(3) }. #external p(1..3). q(X) :- p(X). #script (python) import clingo, sys def main(prg): prg.ground([("base", [])]) print ("Solving...") print ("Answer: 1") out = ("universe(" + str(len(prg.symbolic_atoms)) + ")") for x in prg.symbolic_atoms: out = out + " domain(" + str(x.symbol) + "," + str(x.is_fact).lower() + "," + str(x.is_external).lower() + ")" out = out + " in_domain(p(2)," + str(prg.symbolic_atoms[clingo.Function("p", [3])] is not None).lower() + ")" out = out + " in_domain(p(4)," + str(prg.symbolic_atoms[clingo.Function("p", [4])] is not None).lower() + ")" for x in prg.symbolic_atoms.by_signature("p", 1): out = out + " domain_of_p(" + str(x.symbol) + "," + str(x.is_fact).lower() + "," + str(x.is_external).lower() + ")" for x in prg.symbolic_atoms.signatures: out = out + " sig(" + x[0] + "," + str(x[1]) + ")" print (out) sys.stdout.flush() #end. clingo-5.2.2/app/clingo/tests/python/domain.sol000066400000000000000000000005041320011352300214640ustar00rootroot00000000000000Step: 1 domain(p(1),true,false) domain(p(2),false,true) domain(p(3),false,false) domain(q(1),true,false) domain(q(2),false,false) domain(q(3),false,false) domain_of_p(p(1),true,false) domain_of_p(p(2),false,true) domain_of_p(p(3),false,false) in_domain(p(2),true) in_domain(p(4),false) sig(p,1) sig(q,1) universe(6) UNKNOWN clingo-5.2.2/app/clingo/tests/python/externals.lp000066400000000000000000000005551320011352300220460ustar00rootroot00000000000000#script (python) import sys from clingo import Function def main(prg): prg.ground([("base", [])]) prg.assign_external(Function("a"), True) prg.solve() prg.assign_external(Function("a"), False) prg.solve() prg.assign_external(Function("a"), None) prg.solve() prg.release_external(Function("a")) prg.solve() #end. #external a. clingo-5.2.2/app/clingo/tests/python/externals.sol000066400000000000000000000000531320011352300222210ustar00rootroot00000000000000Step: 1 a Step: 2 Step: 3 a Step: 4 SAT clingo-5.2.2/app/clingo/tests/python/iclingo.lp000066400000000000000000000006641320011352300214660ustar00rootroot00000000000000#program step(k). #external vol(k). p(k). :- vol(k), not 5 { p(K) : K <= k }. #script (python) from clingo import * def main(prg): step = 0 while True: if step > 0: prg.release_external(Function("vol", [step-1])) prg.ground([("step", [step])]) prg.assign_external(Function("vol", [step]), True) ret = prg.solve() if ret.satisfiable is True: break step += 1 #end. clingo-5.2.2/app/clingo/tests/python/iclingo.sol000066400000000000000000000001141320011352300216360ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 p(0) p(1) p(2) p(3) p(4) vol(4) SAT clingo-5.2.2/app/clingo/tests/python/infsup.lp000066400000000000000000000002171320011352300213400ustar00rootroot00000000000000#script (python) import clingo def inf(): return clingo.Infimum def sup(): return clingo.Supremum #end. inf(@inf()). sup(@sup()). clingo-5.2.2/app/clingo/tests/python/infsup.sol000066400000000000000000000000401320011352300215140ustar00rootroot00000000000000Step: 1 inf(#inf) sup(#sup) SAT clingo-5.2.2/app/clingo/tests/python/interrupt.lp000066400000000000000000000007371320011352300220770ustar00rootroot00000000000000#script (python) import clingo def main(prg): prg.ground([("pigeon", [])]) for i in range(0,2): prg.assign_external(clingo.Function("p"), True) prg.solve() prg.assign_external(clingo.Function("p"), False) with prg.solve(async=True) as handle: handle.wait(0.01) prg.interrupt() #end. #const n = 190. #program pigeon. #external p. 1 { p(X); q(X) } 1 :- X = 1..n, not p. :- not n+1 { p(1..n); q(1..n) }, not p. clingo-5.2.2/app/clingo/tests/python/interrupt.sol000066400000000000000000000000541320011352300222510ustar00rootroot00000000000000Step: 1 p Step: 2 Step: 3 p Step: 4 UNKNOWN clingo-5.2.2/app/clingo/tests/python/observer-replace.lp000066400000000000000000000125501320011352300232770ustar00rootroot00000000000000#script (python) import sys from clingo import Function, Tuple class Observer: def __init__(self): self.__delayed = [] self.__symbols = {} self.__reified = [] self.__terms = {} self.__elems = {} def __getattr__(self, name): assert(not name.startswith("_")) def caller(*args): self.__delayed.append((name, args)) return caller def __map(self, lit): sign = False if lit < 0: sign = True lit = -lit ret = self.__symbols.get(lit, Function("__aux")) if sign: ret = Function("neg", [ret]) return ret def init_program(self, incremental): self.__reified.append(Function("init_program", [incremental])) def begin_step(self): self.__reified.append(Function("begin_step", [])) def _rule(self, choice, head, body): head = sorted(set([ self.__map(atm) for atm in head ])) body = sorted(set([ self.__map(lit) for lit in body ])) self.__reified.append(Function("rule", [choice, Tuple(head), Tuple(body)])) def _weight_rule(self, choice, head, lower_bound, body): head = sorted(set([ self.__map(atm) for atm in head ])) body = sorted(set([ Tuple([self.__map(lit), weight]) for lit, weight in body ])) self.__reified.append(Function("weight_rule", [choice, Tuple(head), lower_bound, Tuple(body)])) def _minimize(self, priority, literals): literals = sorted(set([ Tuple([self.__map(lit), weight]) for lit, weight in literals ])) self.__reified.append(Function("minimize", [priority, Tuple(literals)])) def _project(self, atoms): atoms = sorted(set([ self.__map(atm) for atm in atoms ])) self.__reified.append(Function("project", [Tuple(atoms)])) def output_atom(self, symbol, atom): self.__symbols[atom] = symbol self.__reified.append(Function("output_atom", [symbol])) def _output_term(self, symbol, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("output_term", [symbol, Tuple(condition)])) def _output_csp(self, symbol, value, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("output_csp", [symbol, value, Tuple(condition)])) def _external(self, atom, value): self.__reified.append(Function("external", [self.__map(atom), str(value)])) def _assume(self, literals): literals = sorted(set([ self.__map(lit) for lit in literals ])) self.__reified.append(Function("assume", [Tuple(literals)])) def _heuristic(self, atom, type, bias, priority, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("heuristic", [atom, str(type), bias, Tuple(condition)])) def _acyc_edge(self, node_u, node_v, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("acyc_edge", [node_u, node_v, Tuple(condition)])) def theory_term_number(self, term_id, number): self.__terms[term_id] = lambda: number def theory_term_string(self, term_id, name): self.__terms[term_id] = lambda: Function(name) def theory_term_compound(self, term_id, name_id_or_type, arguments): self.__terms[term_id] = lambda: Function(self.__terms[name_id_or_type]().name, [self.__terms[i]() for i in arguments]) def theory_element(self, element_id, terms, condition): self.__elems[element_id] = lambda: Function("elem", [Tuple([self.__terms[i]() for i in terms]), Tuple(sorted(set([ self.__map(lit) for lit in condition ])))]) def _theory_atom(self, atom_id_or_zero, term_id, elements): self.__symbols[atom_id_or_zero] = Function("theory", [self.__terms[term_id](), Tuple(sorted(set([ self.__elems[e]() for e in elements ])))]); def _theory_atom_with_guard(self, atom_id_or_zero, term_id, elements, operator_id, right_hand_side_id): self.__symbols[atom_id_or_zero] = Function("theory", [self.__terms[term_id](), Tuple(sorted(set([ self.__elems[e]() for e in elements ]))), self.__terms[operator_id](), self.__terms[right_hand_side_id]()]); def end_step(self): self.__reified.append(Function("end_step", [])) def finalize(self): for name, args in self.__delayed: if name.startswith("theory_atom"): getattr(self, "_" + name)(*args) for name, args in self.__delayed: if not name.startswith("theory_atom"): getattr(self, "_" + name)(*args) return Context(self.__reified) class Context: def __init__(self, reified): self.__reified = reified[:] def get(self): return self.__reified def main(prg): obs = Observer() prg.register_observer(obs, True) prg.ground([("base", [])]) prg.solve(assumptions=[(Function("b"), False)]) ctx = obs.finalize() print ("Solving...") print ("Answer: 1") print (" ".join([str(x) for x in ctx.get()])) sys.stdout.flush() #end. $x $= 1. $y $= 2. 1 {a; b}. #minimize {1:a; 2:b}. #project a. #show x : a, b. #external a. #heuristic a : b. [1@2,sign] #edge (a,b) : a, b. #theory t { term { + : 1, binary, left }; &a/0 : term, any; &b/1 : term, {=}, term, any }. a :- &a { 1+2,"test": a, b }. b :- &b(3) { } = 17. clingo-5.2.2/app/clingo/tests/python/observer-replace.sol000066400000000000000000000007641320011352300234650ustar00rootroot00000000000000Step: 1 acyc_edge(0,1,(a,b)) assume((neg(b),)) begin_step end_step external(a,"False") heuristic(2,"Sign",1,(b,)) init_program(1) minimize(0,((a,1),(b,2))) output_atom(a) output_atom(b) output_csp(x,1,()) output_csp(y,2,()) output_term(x,(__aux,)) project((a,)) rule(0,(),(__aux,neg(__aux))) rule(0,(__aux,),()) rule(0,(__aux,),(a,b)) rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),)) rule(0,(b,),(theory(b(3),(),=,17),)) rule(1,(a,b),(__aux,)) weight_rule(0,(__aux,),1,((a,1),(b,1))) UNKNOWN clingo-5.2.2/app/clingo/tests/python/observer.cmd000066400000000000000000000000221320011352300220050ustar00rootroot00000000000000--opt-mode=ignore clingo-5.2.2/app/clingo/tests/python/observer.lp000066400000000000000000000124611320011352300216670ustar00rootroot00000000000000#script (python) from clingo import Function, Tuple class Observer: def __init__(self): self.__delayed = [] self.__symbols = {} self.__reified = [] self.__terms = {} self.__elems = {} def __getattr__(self, name): assert(not name.startswith("_")) def caller(*args): self.__delayed.append((name, args)) return caller def __map(self, lit): sign = False if lit < 0: sign = True lit = -lit ret = self.__symbols.get(lit, Function("__aux")) if sign: ret = Function("neg", [ret]) return ret def init_program(self, incremental): self.__reified.append(Function("init_program", [incremental])) def begin_step(self): self.__reified.append(Function("begin_step", [])) def _rule(self, choice, head, body): head = sorted(set([ self.__map(atm) for atm in head ])) body = sorted(set([ self.__map(lit) for lit in body ])) self.__reified.append(Function("rule", [choice, Tuple(head), Tuple(body)])) def _weight_rule(self, choice, head, lower_bound, body): head = sorted(set([ self.__map(atm) for atm in head ])) body = sorted(set([ Tuple([self.__map(lit), weight]) for lit, weight in body ])) self.__reified.append(Function("weight_rule", [choice, Tuple(head), lower_bound, Tuple(body)])) def _minimize(self, priority, literals): literals = sorted(set([ Tuple([self.__map(lit), weight]) for lit, weight in literals ])) self.__reified.append(Function("minimize", [priority, Tuple(literals)])) def _project(self, atoms): atoms = sorted(set([ self.__map(atm) for atm in atoms ])) self.__reified.append(Function("project", [Tuple(atoms)])) def output_atom(self, symbol, atom): self.__symbols[atom] = symbol self.__reified.append(Function("output_atom", [symbol])) def _output_term(self, symbol, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("output_term", [symbol, Tuple(condition)])) def _output_csp(self, symbol, value, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("output_csp", [symbol, value, Tuple(condition)])) def _external(self, atom, value): self.__reified.append(Function("external", [self.__map(atom), str(value)])) def _assume(self, literals): literals = sorted(set([ self.__map(lit) for lit in literals ])) self.__reified.append(Function("assume", [Tuple(literals)])) def _heuristic(self, atom, type, bias, priority, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("heuristic", [atom, str(type), bias, Tuple(condition)])) def _acyc_edge(self, node_u, node_v, condition): condition = sorted(set([ self.__map(lit) for lit in condition ])) self.__reified.append(Function("acyc_edge", [node_u, node_v, Tuple(condition)])) def theory_term_number(self, term_id, number): self.__terms[term_id] = lambda: number def theory_term_string(self, term_id, name): self.__terms[term_id] = lambda: Function(name) def theory_term_compound(self, term_id, name_id_or_type, arguments): self.__terms[term_id] = lambda: Function(self.__terms[name_id_or_type]().name, [self.__terms[i]() for i in arguments]) def theory_element(self, element_id, terms, condition): self.__elems[element_id] = lambda: Function("elem", [Tuple([self.__terms[i]() for i in terms]), Tuple(sorted(set([ self.__map(lit) for lit in condition ])))]) def _theory_atom(self, atom_id_or_zero, term_id, elements): self.__symbols[atom_id_or_zero] = Function("theory", [self.__terms[term_id](), Tuple(sorted(set([ self.__elems[e]() for e in elements ])))]); def _theory_atom_with_guard(self, atom_id_or_zero, term_id, elements, operator_id, right_hand_side_id): self.__symbols[atom_id_or_zero] = Function("theory", [self.__terms[term_id](), Tuple(sorted(set([ self.__elems[e]() for e in elements ]))), self.__terms[operator_id](), self.__terms[right_hand_side_id]()]); def end_step(self): self.__reified.append(Function("end_step", [])) def finalize(self): for name, args in self.__delayed: if name.startswith("theory_atom"): getattr(self, "_" + name)(*args) for name, args in self.__delayed: if not name.startswith("theory_atom"): getattr(self, "_" + name)(*args) return Context(self.__reified) class Context: def __init__(self, reified): self.__reified = reified[:] def get(self): return self.__reified def main(prg): obs = Observer() prg.register_observer(obs) prg.ground([("base", [])]) prg.solve(assumptions=[(Function("b"), False)]) ctx = obs.finalize() prg.add("q", [], "q(@get()).") prg.ground([("q", [])], ctx) prg.solve() #end. $x $= 1. $y $= 2. 1 {a; b}. #minimize {1:a; 2:b}. #project a. #show x : a, b. #external a. #heuristic a : b. [1@2,sign] #edge (a,b) : a, b. #theory t { term { + : 1, binary, left }; &a/0 : term, any; &b/1 : term, {=}, term, any }. a :- &a { 1+2,"test": a, b }. b :- &b(3) { } = 17. clingo-5.2.2/app/clingo/tests/python/observer.sol000066400000000000000000000106401320011352300220460ustar00rootroot00000000000000Step: 1 a x=1 y=2 a x=1 y=2 Step: 2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x x=1 y=2 a q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 a q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 b q(acyc_edge(0,1,(a,b))) q(assume((neg(b),))) q(begin_step) q(end_step) q(external(a,"False")) q(heuristic(2,"Sign",1,(b,))) q(init_program(1)) q(minimize(0,((a,1),(b,2)))) q(output_atom(a)) q(output_atom(b)) q(output_csp(x,1,())) q(output_csp(y,2,())) q(output_term(x,(__aux,))) q(project((a,))) q(rule(0,(),(__aux,neg(__aux)))) q(rule(0,(__aux,),())) q(rule(0,(__aux,),(a,b))) q(rule(0,(a,),(theory(a,(elem((+(1,2),"test"),(a,b)),)),))) q(rule(0,(b,),(theory(b(3),(),=,17),))) q(rule(1,(a,b),(__aux,))) q(weight_rule(0,(__aux,),1,((a,1),(b,1)))) x=1 y=2 SAT clingo-5.2.2/app/clingo/tests/python/parse-term.lp000066400000000000000000000003601320011352300221120ustar00rootroot00000000000000#script (python) import clingo c = clingo.Control() def get(): return [ clingo.parse_term('1'), clingo.parse_term('p(1+2)'), clingo.parse_term('-p'), clingo.parse_term('-p(1)') ] c.ground([("base", [])]) c.solve() #end. p(@get()). clingo-5.2.2/app/clingo/tests/python/parse-term.sol000066400000000000000000000000501320011352300222700ustar00rootroot00000000000000Step: 1 p(-p(1)) p(-p) p(1) p(p(3)) SAT clingo-5.2.2/app/clingo/tests/python/project.lp000066400000000000000000000123101320011352300214770ustar00rootroot00000000000000% Programme de fouille de motifs séquentiels (occurrences minimales) % author : T. Guyet % date : 02/2014 % % parametres de la ligne de commande: % * -c th=? : fixe le seuil (3 par default) % * -c ml=? : profondeur de la recherche (taille max des motifs) (4 par default) % % ces deux valeurs sont remplacées par des constantes du programme : % - th : seuil de frequence, valeur par defaut 3 : elle peut être modifiée par eds parametres lors de l'appel du programme % - nbs : nombre de symboles : defini lors de la construction de la séquence #const th = 3. % liste des symboles fréquents symb(S) :- th { seq(P,S) }, S=1..nbs. %%%%%%%%%%%%%%%%%%%%%%%%%%% %% partie visualisation %%%%%%%%%%%%%%%%%%%%%%%%%%% %#show occ/3. %ne pas afficher les occ pour l'option project #show pattern/2. %#show symb/1. %%%%%%%%%%%%%%%%%%%%%%%%%%% %% partie Contrôle de la résolution %%%%%%%%%%%%%%%%%%%%%%%%%%% #script(python) import sys, os from clingo import * if sys.version_info[0] >= 3: import io as StringIO else: import StringIO modelid = 0 patterns=list() def readsequence(filename): seq = list() src = StringIO.StringIO("""1 5 2 2 3 5 4 2 5 5 6 2 7 1 8 2 9 4 10 2 11 1 12 6 13 1 14 2 15 5 16 3 17 3 18 1 19 3 20 2 """) if src is None: print ("invalid filename:" + str(filename)) return None predpos=0 for line in src: lineelem = line.rstrip('\n\r').lstrip(' ').split(' ') pos=lineelem[0] if( pos==predpos ) : print ("invalid sequence : simultaneous events are not allowed") return None predpos=pos seq.append( int(lineelem[1]) ) src.close() return seq def genASPsequence(seq, prg): i=1 #ajout de la constante pour le nombre de symboles s="#const nbs = "+str(max(seq)) +"." prg.add("base",[], s ) for n in seq: s='seq('+str(i)+","+str(n)+').' prg.add("base", [], s) i=i+1 def on_model(model): pattern={} # map qui associe le numero d'instance à un numero de structure for atom in model.symbols(atoms=True): if atom.name()=="pattern": args = atom.arguments pattern[ args[0] ]=args[1] found=False for i in patterns: if i==pattern: found=True break if not found: patterns.append( pattern ) def main(prg): #Chargement du jeu de données theseq = readsequence("we_cmp.seq.minepi") genASPsequence(theseq, prg) prg.configuration.solve.project = "auto" prg.configuration.solve.models = 0 d = prg.get_const("ml") if d is None: d=4 else: d = d.number prg.ground([("base",[])]) prg.solve() for k in range(2,d+1): prg.ground([("incr",[k])]) prg.solve() #end. %%%%%%%%%%%%%%%%%%%%%%%%%%% %% partie Base %%%%%%%%%%%%%%%%%%%%%%%%%%% % génération de tous les motifs de taille 1 1{ pattern(1, P) : symb(P) } 1. % on genere les occurrences pour chacun des patterns-singletons : le numero de l'instance est la position initiale (unique) ! { occ(P, 1, P) : seq(P, S) } :- pattern(1,S). % pour imposer d'avoir nécessairement toutes les occurrenres d'un motifs (et pas simplement des sous-ensembles): :- seq(P, S), not occ(P, 1, P), pattern(1,S). %%%%%%%%%%%% %% cas des tailles 2 %1{ pattern(2, P) : symb(P) } 1. % extention des occurrences du motif %0{ occ(I,2,Q) : seq(Q,S), pattern(2,S), Q>P } 1 :- occ(I, 1, P). %:- occ(I, 1, P), occ(I, 2, Q), seq(P',S), pattern(2,S), PP } 1 :- occ(I, n-1, P). %0{ possocc(I,n,Q) : seq(Q,S), pattern(n,S), Q>P } 1 :- occ(I, n-1, P). %#show occ/3. % %#external closed(1..nbs). %% pour savoir si le motif plus petit est fermé par l'ajout de S: %nbnext(I,n-1,N) :- occ(I, n-1, P), N={ occ(I,n,Q) }. %closed(S) :- { nbnext(I,n-1,N) : N=0 } 0, pattern(n,S). %#show closed/1. % On prend le premier symbole de la fin du motif juste apres la fin d'une occurrence du motif "inferieur" : :- occ(I, n-1, P), occ(I, n, Q), seq(P',S), pattern(n,S), P= 0) item = self.__map_item(str(item)) resize(self.__seq_atoms[sid][1], index + 1); self.__seq_atoms[sid][1][index] = item def __add_pat_atoms(self, init, atom): for elem in atom.elements: lit = init.solver_literal(elem.condition_id) index, item = elem.terms index = index.number assert(index >= 0) item = self.__map_item(str(item)) pat = (index, item) if lit not in self.__pat_atoms: init.add_watch(lit) self.__pat_atoms.setdefault(lit, []).append(pat) self.__pat_len = max(self.__pat_len, index + 1) def __init_occ_list(self): for item in self.__item_map: self.__occ_list.append([]) sid = 0 for seq in self.__seq_atoms: for item in set(seq[1]): assert(item is not None) self.__occ_list[item].append(sid) sid += 1 def init(self, init): for atom in init.theory_atoms: term = atom.term args = term.arguments if term.name == "seq" and len(args) == 1: self.__add_seq_atom(init, args[0].number, atom) if term.name == "pat" and len(args) == 0: self.__add_pat_atoms(init, atom) self.__init_occ_list() # {{{1 Tracing Functions def __str_item(self, iid): for item, jid in self.__item_map.iteritems(): if iid == jid: return item def __str_items(self, items): s = "" for item in items: s+= self.__str_item(item) return s def __str_pat(self, state): s = "" for pat in state.pat: s+= "." if pat is None else self.__str_item(pat[1]) return s def __str_seq(self, lit): for seq in self.__seq_atoms: if seq[0] == lit: return self.__str_items(seq[1]) # {{{1 Propagation def __propagate_sequence_lit(self, state, control, sid, lit): state.seq_active[sid] = None state.stack.append(-sid-1) if not control.assignment.is_true(lit): klaus = [lit] for pat in state.pat: if pat is not None: klaus.append(-pat[0]) return control.add_clause(klaus) and control.propagate() return True def __propagate_sequence(self, state, control, sid, lit, items): if state.pat_assigned < self.__pat_len and control.assignment.is_false(lit): return True iid = 0 for pat in state.pat: while True: if iid == len(items): return self.__propagate_sequence_lit(state, control, sid, -lit) iid+= 1 if pat is None or items[iid-1] == pat[1]: break return state.pat_assigned < self.__pat_len or self.__propagate_sequence_lit(state, control, sid, lit) def propagate(self, control, changes): state = self.__state(control.thread_id) if len(state.trail) == 0 or state.trail[-1][0] < control.assignment.decision_level: state.trail.append((control.assignment.decision_level, len(state.stack))) for lit in changes: for pat in self.__pat_atoms[lit]: if state.pat[pat[0]] is not None: # this case should not occur if the pattern is generated properly old = state.pat[pat[0]][0] assert(control.assignment.is_true(old)) control.add_clause([-lit, -old]) and control.propagate() return else: state.stack.append(pat[0]) state.pat_assigned+= 1 state.pat[pat[0]] = (lit, pat[1]) for sid in self.__occ_list[pat[1]]: if state.seq_active[sid] and not self.__propagate_sequence(state, control, sid, *self.__seq_atoms[sid]): return def undo(self, thread_id, assign, undo): state = self.__state(thread_id) sid = state.trail[-1][1] for psid in state.stack[sid:]: if psid >= 0: state.pat[psid] = None state.pat_assigned-= 1 else: state.seq_active[-psid-1] = True del state.stack[sid:] state.trail.pop() # }}}1 def main(prg): prg.configuration.solve.opt_mode = "optN" prg.register_propagator(Propagator()) prg.ground([("base", [])]) # :- not sup(U), seq(U,_,_), n == 0. if prg.get_const("n").number == 0: grouped = {} for atom in prg.symbolic_atoms.by_signature("seq", 3): grouped.setdefault(atom.symbol.arguments[0], []).append(atom.literal) for key, value in sorted(grouped.items()): a = prg.backend.add_atom() for l in value: prg.backend.add_rule([a], [l]) prg.backend.add_rule([], [-prg.symbolic_atoms[clingo.Function("sup", [key])].literal, a]) # :- sup(U), pat(_,I), not seq(U,_,I). grouped_pat, grouped_seq = {}, set() for atom in prg.symbolic_atoms.by_signature("pat", 2): grouped_pat.setdefault(atom.symbol.arguments[1], []).append(atom.literal) for atom in prg.symbolic_atoms.by_signature("seq", 3): grouped_seq.add((atom.symbol.arguments[0], atom.symbol.arguments[2])) projected_pat, projected_seq = {}, {} for key, value in sorted(grouped_pat.items()): a = prg.backend.add_atom() for l in value: prg.backend.add_rule([a], [l]) projected_pat[key] = a for atom in prg.symbolic_atoms.by_signature("sup", 1): for key, lit in sorted(projected_pat.items()): if (atom.symbol.arguments[0], key) not in grouped_seq: prg.backend.add_rule([], [atom.literal, lit]) prg.solve() #end. #show pat/2. #theory seq { term { }; &seq/1 : term, body; &pat/0 : term, directive }. #const n = 5. 1 { pat(P,I) : seq(_,_,I) } 1 :- P = 0..(n-1). &pat { P,I : pat(P,I) }. sup(U) :- &seq(U) { P,I : seq(U,P,I) }, seq(U,_,_). #maximize { 1,U : sup(U) }. % abaca seq(0,0,a). seq(0,1,b). seq(0,2,a). seq(0,3,c). seq(0,4,a). % abdca seq(1,0,a). seq(1,1,b). seq(1,2,d). seq(1,3,c). seq(1,4,a). % aedca seq(2,0,a). seq(2,1,e). seq(2,2,d). seq(2,3,c). seq(2,4,a). clingo-5.2.2/app/clingo/tests/python/propagator.sol000066400000000000000000000002351320011352300223740ustar00rootroot00000000000000Step: 1 pat(0,a) pat(1,b) pat(2,a) pat(3,c) pat(4,a) pat(0,a) pat(1,b) pat(2,d) pat(3,c) pat(4,a) pat(0,a) pat(1,e) pat(2,d) pat(3,c) pat(4,a) OPTIMUM FOUND clingo-5.2.2/app/clingo/tests/python/queens.lp000066400000000000000000000014501320011352300213340ustar00rootroot00000000000000#script (python) import clingo def main(prg): step = 1 stop = 10 while True: if step > 1: prg.release_external(clingo.Function("volatile", [step-1])) prg.ground([("cumulative", [step])]) prg.assign_external(clingo.Function("volatile", [step]), True) ret = prg.solve() if step == stop: break step = step + 1 #end. #program cumulative(k). dim(k). {q(X,k) : dim(X)}. {q(k,Y) : dim(Y), Y 0 else Function(name) def on_model(model): models.append(fun("model", split(model))) models.append(fun("shown", sorted(model.symbols(shown=True)))) models.append(fun("atoms", sorted(model.symbols(atoms=True)))) models.append(fun("terms", sorted(model.symbols(terms=True)))) models.append(fun("csp", sorted(model.symbols(csp=True)))) def main(prg): prg.ground([("base", [])]) prg.solve(on_model=on_model) prg.ground([("result", [])]) prg.solve() #end. $1 $= 11. { b }. c. $x $= 42. $y(1) $= 13. $y(2) $= 23. $z $= 7. #show $1. #show c/0. #show a : b. #show $x/0. #show $y(1) : b. #show $y(2) : not b. #show $y(3) : b. #program result. res(X) :- X = @getModels(). #show res/1. clingo-5.2.2/app/clingo/tests/python/show.sol000066400000000000000000000012241320011352300211750ustar00rootroot00000000000000Step: 1 1=11 a c x=42 y(1)=13 1=11 c x=42 y(2)=23 Step: 2 1=11 a c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(1)=13 1=11 c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(2)=23 SAT clingo-5.2.2/app/clingo/tests/python/sokoban.cmd000066400000000000000000000000061320011352300216140ustar00rootroot00000000000000-q1,2 clingo-5.2.2/app/clingo/tests/python/sokoban.lp000066400000000000000000000046031320011352300214730ustar00rootroot00000000000000#script(python) from clingo import Function, SolveResult from sys import stderr def main(prg): prg.configuration.solve.opt_mode = "optN" prg.configuration.solve.models = 0 t = 0 e = 2 parts = [] parts.append(("base", [])) parts.append(("state", [t])) while True: prg.ground(parts) prg.release_external(Function("volatile", [t-1])) prg.cleanup() prg.assign_external(Function("volatile", [t]), True) ret = prg.solve() if ret.satisfiable is False and t > 20: break if ret.satisfiable is True: e -= 1 if e == 0: break t += 1 parts = [] parts.append(("trans", [t])) parts.append(("state", [t])) #end. #program base. dir(u, 0, 1). dir(d, 0,-1). dir(r, 1, 0). dir(l,-1, 0). box(X,Y,0) :- initial_box(X,Y). at(X,Y,0) :- initial_at(X,Y). #program trans(t). % reachable places route(X,Y,t) :- at(X,Y,t-1). route(X+DX,Y+DY,t) :- route(X,Y,t), dir(D,DX,DY), square(X+DX,Y+DY), not box(X+DX,Y+DY,t-1). % select place to move from 1 { push_from(X,Y,D,t) : route(X,Y,t), dir(D,DX,DY), square(X+DX,Y+DY), box(X+DX,Y+DY,t-1) } 1. % move horizontally or vertically move(X,Y,D,t) :- push_from(X,Y,D,t). { move(X+DX,Y+DY,D,t) } :- move(X,Y,D,t), dir(D,DX,DY), square(X+2*DX,Y+2*DY), not box(X+2*DX,Y+2*DY,t-1). % target location move_to(X,Y,D,t) :- move(X,Y,D,t), not move(X+DX,Y+DY,D,t), dir(D,DX,DY). push_to(X+DX,Y+DY,t) :- move_to(X,Y,D,t), dir(D,DX,DY). % state transition at(X-DX,Y-DY,t) :- move_to(X,Y,D,t), dir(D,DX,DY). box(X,Y,t) :- push_to(X,Y,t). box(X,Y,t) :- box(X,Y,t-1), not push_from(X-DX,Y-DY,D,t) : dir(D,DX,DY). #show push_from(X,Y,t) : push_from(X,Y,D,t). #show move_to(X,Y,t) : move_to(X,Y,D,t). #show push_to/3. #program state(t). #minimize { X@1,Y,t : box(X,Y,t) }. #minimize { Y@2,X,t : box(X,Y,t) }. #external volatile(t). :- target_square(X,Y), not box(X,Y,t), volatile(t). #program base. square(1, 1). target_square(1, 1). square(2, 1). target_square(2, 1). square(1, 2). target_square(1, 2). square(2, 2). target_square(2, 2). initial_at(5,3). square(1, 3). square(2, 3). initial_box(2, 3). square(3, 3). square(4, 3). initial_box(4, 3). square(5, 3). square(1, 4). square(2, 4). square(3, 4). initial_box(3, 4). square(4, 4). initial_box(4, 4). square(5, 4). square(1, 5). square(2, 5). square(3, 5). square(4, 5). square(5, 5). clingo-5.2.2/app/clingo/tests/python/sokoban.sol000066400000000000000000000024451320011352300216570ustar00rootroot00000000000000Step: 1 Step: 2 Step: 3 Step: 4 Step: 5 Step: 6 Step: 7 Step: 8 Step: 9 move_to(1,2,3) move_to(1,3,6) move_to(2,2,1) move_to(2,3,2) move_to(2,3,8) move_to(2,4,5) move_to(3,3,7) move_to(3,4,4) push_from(1,4,3) push_from(1,5,6) push_from(2,4,1) push_from(2,4,8) push_from(3,5,4) push_from(4,3,7) push_from(5,3,2) push_from(5,4,5) push_to(1,1,3) push_to(1,2,6) push_to(1,3,2) push_to(1,4,5) push_to(2,1,1) push_to(2,2,8) push_to(2,3,7) push_to(3,3,4) Step: 10 move_to(1,2,3) move_to(1,3,6) move_to(1,3,9) move_to(2,2,1) move_to(2,3,2) move_to(2,3,8) move_to(2,4,5) move_to(3,3,7) move_to(3,4,4) push_from(1,3,9) push_from(1,4,3) push_from(1,5,6) push_from(2,4,1) push_from(2,4,8) push_from(3,5,4) push_from(4,3,7) push_from(5,3,2) push_from(5,4,5) push_to(1,1,3) push_to(1,2,6) push_to(1,2,9) push_to(1,3,2) push_to(1,4,5) push_to(2,1,1) push_to(2,2,8) push_to(2,3,7) push_to(3,3,4) move_to(1,2,3) move_to(1,3,6) move_to(2,2,1) move_to(2,3,2) move_to(2,3,8) move_to(2,3,9) move_to(2,4,5) move_to(3,3,7) move_to(3,4,4) push_from(1,4,3) push_from(1,5,6) push_from(2,3,9) push_from(2,4,1) push_from(2,4,8) push_from(3,5,4) push_from(4,3,7) push_from(5,3,2) push_from(5,4,5) push_to(1,1,3) push_to(1,2,6) push_to(1,3,2) push_to(1,4,5) push_to(2,1,1) push_to(2,2,8) push_to(2,2,9) push_to(2,3,7) push_to(3,3,4) OPTIMUM FOUND clingo-5.2.2/app/clingo/tests/python/tag.lp000066400000000000000000000013031320011352300206040ustar00rootroot00000000000000#script(python) class Tag: def __init__(self): self.__add = True def flip(self): self.__add = not self.__add def init(self, init): for atom in init.symbolic_atoms: init.add_watch(init.solver_literal(atom.literal)) init.add_watch(-init.solver_literal(atom.literal)) def propagate(self, control, changes): if self.__add: control.add_clause([], tag=True) return True def undo(self, thread_id, assign, undo): pass def check(self, control): return True def main(prg): prg.ground([("base", [])]) p = Tag() prg.register_propagator(p) prg.solve() p.flip() prg.solve() #end. {a}. clingo-5.2.2/app/clingo/tests/python/tag.sol000066400000000000000000000000271320011352300207700ustar00rootroot00000000000000Step: 1 Step: 2 a SAT clingo-5.2.2/app/clingo/tests/python/test.lp000066400000000000000000000023451320011352300210170ustar00rootroot00000000000000#script (python) import clingo import sys def writeln(s): sys.stdout.write(str(s)) sys.stdout.write("\n") sys.stdout.flush() def on_model(x): writeln("Answer: 42") writeln( "hasA(" + str(x.contains(clingo.Function("a"))).lower() + ") " + "hasVolatile(" + str(x.contains(clingo.Function("volatile", [9]))).lower() + ") " + "model(" + ",".join(sorted(map(str, x.symbols(shown=True)))) + ") ") def on_finish(ret): writeln("Answer: 42") writeln("on_finish") def main (prg): n = prg.get_const("n").number parts = [] parts.append(("base", [])) prg.ground(parts) prg.solve() prg.add("test", ["x"], "test(x).") parts.append(("test", [clingo.Function("f", [1,2])])) for i in range(1,n+1): parts.append(("cumulative", [i])) prg.ground(parts) parts = [] with prg.solve(on_model=on_model, on_finish=on_finish, async=True) as handle: handle.wait(0) ret = handle.get() writeln("Answer: 42") writeln(ret) #end. #const n = 10. #program base. a. #program cumulative(k). 1 { c(k) } 1. q(k) :- c(k). r(k,X) :- test(X). #external volatile(k). :- not c(5), not volatile(k). volatile(k-1). clingo-5.2.2/app/clingo/tests/python/test.sol000066400000000000000000000071771320011352300212110ustar00rootroot00000000000000Step: 1 a Step: 2 UNSAT on_finish Step: 3 UNSAT on_finish Step: 4 UNSAT on_finish Step: 5 UNSAT on_finish Step: 6 SAT a c(1) c(2) c(3) c(4) c(5) q(1) q(2) q(3) q(4) q(5) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),q(1),q(2),q(3),q(4),q(5),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4)) on_finish Step: 7 SAT a c(1) c(2) c(3) c(4) c(5) c(6) q(1) q(2) q(3) q(4) q(5) q(6) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),q(1),q(2),q(3),q(4),q(5),q(6),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5)) on_finish Step: 8 SAT a c(1) c(2) c(3) c(4) c(5) c(6) c(7) q(1) q(2) q(3) q(4) q(5) q(6) q(7) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),q(1),q(2),q(3),q(4),q(5),q(6),q(7),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6)) on_finish Step: 9 SAT a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7)) on_finish Step: 10 SAT a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8) hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8)) on_finish Step: 11 SAT a c(1) c(10) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(10) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(10,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8) volatile(9) hasA(true) hasVolatile(true) model(a,c(1),c(10),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(10),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(10,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8),volatile(9)) on_finish SAT clingo-5.2.2/app/clingo/tests/run.py000077500000000000000000000140611320011352300173410ustar00rootroot00000000000000#!/usr/bin/python import re import os import os.path import sys import subprocess as sp import difflib as dl import argparse parser = argparse.ArgumentParser(description=""" Can be used to run and normalize tests. Additional options can be passed to clingo by adding them at the end of the command line preceded by '--'. """) parser.add_argument('-c', '--clingo', default=None, help="path to clingo executable") subparsers = parser.add_subparsers(dest="action", help="sub-command --help") subparsers.required = True parser_run = subparsers.add_parser('run', help='run all tests') parser_normalize = subparsers.add_parser('normalize', help='normalize the output of clingo') parser_normalize.add_argument("file") argv = sys.argv[1:] extra_argv = [] if "--" in argv: extra_argv = argv[argv.index("--")+1:] argv = argv[:argv.index("--")] parse_ret = parser.parse_args(argv) if parse_ret.action is None: print (parser.usage) exit(0) clingo = parse_ret.clingo def find_clingo(): clingos = [ "build/debug/bin/clingo", "build/release/bin/clingo", "build/bin/clingo", "build/cmake/bin/clingo", "build/bin/Debug/clingo.exe", "build/bin/Release/clingo.exe", ] for x in clingos: x = os.path.normpath("{}/../../../{}".format(wd, x)) if os.path.exists(x): return x return None wd = os.path.normpath(os.path.dirname(__file__)) if clingo is None: clingo = find_clingo() if clingo is None: print ("no usable clingo version found") exit(1) def reorder(out): return out res = [] current = [] for line in out.splitlines(): if line.startswith("Step: ") or line.startswith("SAT") or line.startswith("UNSAT") or line.startswith("UNKNOWN") or line.startswith("OPTIMUM FOUND"): res.extend(sorted(current)) res.append(line) current = [] else: current.append(" ".join(sorted(line.split(" ")))) return "\n".join(res) def normalize(out): state=0 current=[] step=0 result="ERROR" norm=[] for line in out.split("\n"): if state == 1: if step > 0: norm.append("Step: {}".format(step)) models = [] for model in current: models.append(" ".join(sorted(model))) for model in sorted(models): norm.append(model) step += 1 state = 0 current = [] if state == 2: current.append(line.strip().split(" ")) state=0 elif line.startswith("Solving..."): state = 1 elif line.startswith("Answer: "): state = 2 elif line.startswith("SATISFIABLE"): result="SAT" state=1 elif line.startswith("UNSATISFIABLE"): result="UNSAT" state=1 elif line.startswith("UNKNOWN"): result="UNKNOWN" state=1 elif line.startswith("OPTIMUM FOUND"): result="OPTIMUM FOUND" state=1 norm.append(result) norm.append("") return "\n".join(norm) if parse_ret.action == "normalize": args = [clingo, "0", parse_ret.file, "-Wnone"] b = os.path.splitext(parse_ret.file)[0] if os.path.exists(b + ".cmd"): for x in open(b + ".cmd", 'rU'): args.extend(x.strip().split()) args.extend(extra_argv) out, err = sp.Popen(args, stderr=sp.PIPE, stdout=sp.PIPE, universal_newlines=True).communicate() sys.stdout.write(normalize(out)) exit(0) if parse_ret.action == "run": total = 0 failed = 0 out, err = sp.Popen([clingo, "--version"], stderr=sp.PIPE, stdout=sp.PIPE, universal_newlines=True).communicate() with_python = out.find("with Python") > 0 with_lua = out.find("with Lua") > 0 with_threads = out.find("WITH_THREADS=1") > 0 for root, dirs, files in os.walk(wd): for f in sorted(files): if f.endswith(".lp"): b = os.path.join(root, f[:-3]) inst = open(b + ".lp", 'rU').read() if (not with_python and re.search(r"#script[ ]*\(python\)", inst)) or \ (not with_lua and re.search(r"#script[ ]*\(lua\)", inst)) or \ (not with_threads and re.search("async=", inst)) or \ (not with_threads and re.search("solve_async", inst)): continue total+= 1 sys.stdout.flush() args = [clingo, "0", b + ".lp", "-Wnone"] if os.path.exists(b + ".cmd"): for x in open(b + ".cmd", 'rU'): args.extend(x.strip().split()) args.extend(extra_argv) out, err = sp.Popen(args, stderr=sp.PIPE, stdout=sp.PIPE, universal_newlines=True).communicate() norm = normalize(out) sol = reorder(open(b + ".sol", 'rU').read()) if norm != sol: failed+= 1 print print ("-" * 79) print (" ".join(args)) print ("." * 79) print print ("FAILED:") d = dl.Differ() for line in list(d.compare(sol.splitlines(), norm.splitlines())): if not line.startswith(" "): print (line) print print ("." * 79) print print ("STDOUT:") print print (out) print print ("." * 79) print print ("STDERR:") print print (err) print sys.stdout.flush() print ("=" * 79) if failed > 0: print ("Some tests failed ({} of {} test cases)".format(failed, total)) print exit(1) else: print ("All tests passed ({} test cases)".format(total)) print exit(0) clingo-5.2.2/app/gringo/000077500000000000000000000000001320011352300150265ustar00rootroot00000000000000clingo-5.2.2/app/gringo/CMakeLists.txt000066400000000000000000000006761320011352300175770ustar00rootroot00000000000000# [[[source: . set(ide_source_group "Source Files") set(source-group "${CMAKE_CURRENT_SOURCE_DIR}/main.cc") source_group("${ide_source_group}" FILES ${source-group}) set(source ${source-group}) # ]]] add_executable(gringo ${header} ${source}) target_link_libraries(gringo PRIVATE libpyclingo libluaclingo libclingo) set_target_properties(gringo PROPERTIES FOLDER exe) install(TARGETS gringo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) clingo-5.2.2/app/gringo/main.cc000066400000000000000000000033411320011352300162620ustar00rootroot00000000000000// {{{ MIT License // Copyright 2017 Roland Kaminski // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // }}} #ifdef CLINGO_WITH_PYTHON # include #endif #ifdef CLINGO_WITH_LUA # include #endif #include #include extern "C" CLINGO_VISIBILITY_DEFAULT int gringo_main_(int argc, char *argv[]); int main(int argc, char *argv[]) { # ifdef CLINGO_WITH_PYTHON if (!clingo_register_python_()) { std::cerr << clingo_error_message() << std::endl; return 1; } # endif # ifdef CLINGO_WITH_LUA if (!clingo_register_lua_(nullptr)) { std::cerr << clingo_error_message() << std::endl; return 1; } # endif return gringo_main_(argc, argv); } clingo-5.2.2/app/luaclingo/000077500000000000000000000000001320011352300155165ustar00rootroot00000000000000clingo-5.2.2/app/luaclingo/CMakeLists.txt000066400000000000000000000023001320011352300202510ustar00rootroot00000000000000# [[[source: . set(ide_source_group "Source Files") set(source-group "${CMAKE_CURRENT_SOURCE_DIR}/main.cc") source_group("${ide_source_group}" FILES ${source-group}) set(source ${source-group}) # ]]] add_library(luaclingo SHARED ${source}) target_link_libraries(luaclingo PRIVATE libluaclingo) set_target_properties(luaclingo PROPERTIES FOLDER lib OUTPUT_NAME clingo PREFIX "") target_include_directories(luaclingo PRIVATE ${LUA_INCLUDE_DIR}) if (CMAKE_RUNTIME_OUTPUT_DIRECTORY) set_target_properties(luaclingo PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lua) endif() if (CMAKE_LIBRARY_OUTPUT_DIRECTORY) set_target_properties(luaclingo PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lua) endif() if (CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set_target_properties(luaclingo PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/lua) endif() if (LUACLINGO_SUFFIX) set_target_properties(luaclingo PROPERTIES SUFFIX ${LUACLINGO_SUFFIX}) endif() if (LUACLINGO_INSTALL_DIR) install(TARGETS luaclingo RUNTIME DESTINATION ${LUACLINGO_INSTALL_DIR} LIBRARY DESTINATION ${LUACLINGO_INSTALL_DIR}) endif() clingo-5.2.2/app/luaclingo/main.cc000066400000000000000000000030161320011352300167510ustar00rootroot00000000000000// {{{ MIT License // Copyright 2017 Roland Kaminski // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // }}} #include #if defined _WIN32 || defined __CYGWIN__ # define VISIBILITY_DEFAULT __declspec (dllexport) #else # if __GNUC__ >= 4 # define VISIBILITY_DEFAULT __attribute__ ((visibility ("default"))) # else # define VISIBILITY_DEFAULT # endif #endif extern "C" VISIBILITY_DEFAULT int luaopen_clingo(lua_State *L) { clingo_register_lua_(L); return clingo_init_lua_(L); } clingo-5.2.2/app/pyclingo/000077500000000000000000000000001320011352300153655ustar00rootroot00000000000000clingo-5.2.2/app/pyclingo/CMakeLists.txt000066400000000000000000000043101320011352300201230ustar00rootroot00000000000000# [[[source: . set(ide_source_group "Source Files") set(source-group "${CMAKE_CURRENT_SOURCE_DIR}/main.cc") source_group("${ide_source_group}" FILES ${source-group}) set(source ${source-group}) # ]]] if (NOT PYCLINGO_INSTALL_DIR AND PYTHON_EXECUTABLE) if (PYCLINGO_USER_INSTALL) execute_process(COMMAND ${PYTHON_EXECUTABLE} -m site --user-site OUTPUT_VARIABLE PYCLINGO_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) elseif(PYCLINGO_USE_INSTALL_PREFIX) execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CLINGO_SOURCE_DIR}/cmake/python-site.py prefix "${CMAKE_INSTALL_PREFIX}" OUTPUT_VARIABLE PYCLINGO_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) else() execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CLINGO_SOURCE_DIR}/cmake/python-site.py prefix OUTPUT_VARIABLE PYCLINGO_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) endif() endif() if (NOT PYCLINGO_SUFFIX) if (PYTHON_EXECUTABLE) execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CLINGO_SOURCE_DIR}/cmake/python-site.py suffix OUTPUT_VARIABLE PYCLINGO_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) else() if (CYGWIN) set(PYCLINGO_SUFFIX ".dll") elseif (UNIX) set(PYCLINGO_SUFFIX ".so") else() set(PYCLINGO_SUFFIX ".pyd") endif() endif() endif() add_library(pyclingo SHARED ${source}) target_link_libraries(pyclingo PRIVATE libpyclingo) set_target_properties(pyclingo PROPERTIES FOLDER lib OUTPUT_NAME clingo SUFFIX ${PYCLINGO_SUFFIX} PREFIX "") target_include_directories(pyclingo PRIVATE ${PYTHON_INCLUDE_DIRS}) if (CMAKE_RUNTIME_OUTPUT_DIRECTORY) set_target_properties(pyclingo PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/python) endif() if (CMAKE_LIBRARY_OUTPUT_DIRECTORY) set_target_properties(pyclingo PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/python) endif() if (CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set_target_properties(pyclingo PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/python) endif() if (PYCLINGO_INSTALL_DIR) install(TARGETS pyclingo RUNTIME DESTINATION ${PYCLINGO_INSTALL_DIR} LIBRARY DESTINATION ${PYCLINGO_INSTALL_DIR}) endif() clingo-5.2.2/app/pyclingo/main.cc000066400000000000000000000037321320011352300166250ustar00rootroot00000000000000// {{{ MIT License // Copyright 2017 Roland Kaminski // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // }}} // NOTE: the python header has a linker pragma to link with python_d.lib // when _DEBUG is set which is not part of official python releases #if defined(_MSC_VER) && defined(_DEBUG) && !defined(CLINGO_UNDEF__DEBUG) #undef _DEBUG #include #define _DEBUG #else #include #endif #include #if defined _WIN32 || defined __CYGWIN__ # define VISIBILITY_DEFAULT __declspec (dllexport) #else # if __GNUC__ >= 4 # define VISIBILITY_DEFAULT __attribute__ ((visibility ("default"))) # else # define VISIBILITY_DEFAULT # endif #endif #if PY_MAJOR_VERSION >= 3 extern "C" VISIBILITY_DEFAULT PyObject *PyInit_clingo() { clingo_register_python_(); return (PyObject*)clingo_init_python_(); } #else extern "C" VISIBILITY_DEFAULT void initclingo() { clingo_register_python_(); clingo_init_python_(); } #endif clingo-5.2.2/app/reify/000077500000000000000000000000001320011352300146575ustar00rootroot00000000000000clingo-5.2.2/app/reify/CMakeLists.txt000066400000000000000000000010161320011352300174150ustar00rootroot00000000000000# [[[source: . set(ide_source_group "Source Files") set(source-group "${CMAKE_CURRENT_SOURCE_DIR}/main.cc") source_group("${ide_source_group}" FILES ${source-group}) set(source ${source-group}) # ]]] add_executable(reify ${header} ${source}) target_link_libraries(reify PRIVATE libreify libpotassco) target_include_directories(reify PRIVATE "$") set_target_properties(reify PROPERTIES FOLDER exe) install(TARGETS reify RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) clingo-5.2.2/app/reify/main.cc000066400000000000000000000067011320011352300161160ustar00rootroot00000000000000// {{{ MIT License // Copyright 2017 Roland Kaminski // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // }}} #include #include #include #include "reify/program.hh" #include "clingo.h" struct ReifyOptions { bool calculateSCCs = false; bool reifyStep = false; }; class ReifyApp : public Potassco::Application { public: virtual const char* getName() const { return "reify"; } virtual const char* getVersion() const { return CLINGO_VERSION; } protected: virtual void initOptions(Potassco::ProgramOptions::OptionContext& root) { using namespace Potassco::ProgramOptions; OptionGroup reify("Reify Options"); reify.addOptions() ("sccs,c", flag(opts_.calculateSCCs), "calculate strongly connected components\n") ("steps,s", flag(opts_.reifyStep), "add step numbers to generated facts\n"); root.add(reify); OptionGroup basic("Basic Options"); basic.addOptions() ("file,f,@2", storeTo(input_), "Input files") ; root.add(basic); } virtual void validateOptions(const Potassco::ProgramOptions::OptionContext&, const Potassco::ProgramOptions::ParsedOptions&, const Potassco::ProgramOptions::ParsedValues&) { } virtual void setup() { } static bool parsePositional(std::string const &, std::string& out) { out = "file"; return true; } virtual Potassco::ProgramOptions::PosOption getPositional() const { return parsePositional; } virtual void printHelp(const Potassco::ProgramOptions::OptionContext& root) { printf("%s version %s\n", getName(), getVersion()); printUsage(); Potassco::ProgramOptions::FileOut out(stdout); root.description(out); printf("\n"); printUsage(); } virtual void printVersion() { Application::printVersion(); printf("License: The MIT License \n"); fflush(stdout); } virtual void run() { Reify::Reifier reify(std::cout, opts_.calculateSCCs, opts_.reifyStep); if (input_.empty() || input_ == "-") { reify.parse(std::cin); } else { std::ifstream ifs(input_); reify.parse(ifs); } } private: std::string input_; ReifyOptions opts_; }; int main(int argc, char **argv) { ReifyApp app; return app.main(argc, argv); } clingo-5.2.2/app/web/000077500000000000000000000000001320011352300143165ustar00rootroot00000000000000clingo-5.2.2/app/web/CMakeLists.txt000066400000000000000000000012241320011352300170550ustar00rootroot00000000000000# [[[source: . set(ide_source_group "Source Files") set(source-group "${CMAKE_CURRENT_SOURCE_DIR}/main.cc") source_group("${ide_source_group}" FILES ${source-group}) set(source ${source-group}) # ]]] add_executable(web ${header} ${source}) target_link_libraries(web libclingo libclasp libluaclingo libpyclingo) set_target_properties(web PROPERTIES FOLDER exe) target_include_directories(web PRIVATE "$" "$") set_target_properties(web PROPERTIES LINK_FLAGS "-s EXPORTED_FUNCTIONS='[\"_run\"]'") set_target_properties(web PROPERTIES OUTPUT_NAME "clingo") clingo-5.2.2/app/web/main.cc000066400000000000000000000054131320011352300155540ustar00rootroot00000000000000// {{{ MIT License // Copyright 2017 Roland Kaminski // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // }}} #ifdef CLINGO_WITH_LUA # include #endif #include "clingo/clingo_app.hh" #include "clingo/scripts.hh" #include class ExitException : public std::exception { public: ExitException(int status) : status_(status) { std::ostringstream oss; oss << "exited with status: " << status_; msg_ = oss.str(); } int status() const { return status_; } char const *what() const noexcept { return msg_.c_str(); } ~ExitException() = default; private: std::string msg_; int status_; }; struct WebApp : Gringo::ClingoApp { void exit(int status) const { throw ExitException(status); } }; extern "C" int run(char const *program, char const *options) { try { #ifdef CLINGO_WITH_LUA Gringo::g_scripts() = Gringo::Scripts(); clingo_register_lua_(nullptr); #endif std::streambuf* orig = std::cin.rdbuf(); auto exit(Gringo::onExit([orig]{ std::cin.rdbuf(orig); })); std::istringstream input(program); std::cin.rdbuf(input.rdbuf()); std::vector> opts; opts.emplace_back(std::initializer_list{'c','l','i','n','g','o','\0'}); std::istringstream iss(options); for (std::istream_iterator it(iss), ie; it != ie; ++it) { opts.emplace_back(it->c_str(), it->c_str() + it->size() + 1); } std::vector args; for (auto &opt : opts) { args.emplace_back(opt.data()); } WebApp app; args.emplace_back(nullptr); return app.main(args.size()-2, args.data()); } catch (ExitException const &e) { return e.status(); } } clingo-5.2.2/clasp/000077500000000000000000000000001320011352300140635ustar00rootroot00000000000000clingo-5.2.2/clasp/.gitignore000066400000000000000000000000521320011352300160500ustar00rootroot00000000000000*.swp build* .vscode* CMakeLists.txt.user clingo-5.2.2/clasp/.travis.yml000066400000000000000000000023561320011352300162020ustar00rootroot00000000000000sudo: false language: cpp matrix: include: - os: linux compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - george-edison55-precise-backports packages: - g++-4.9 - cmake - cmake-data env: - COMPILER='g++-4.9' - os: linux compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - george-edison55-precise-backports packages: - g++-5 - cmake - cmake-data env: - COMPILER='g++-5' - os: osx osx_image: xcode8 env: - COMPILER='clang++' install: - export CMAKE=cmake - export CXX=$COMPILER - $CMAKE --version - $CXX --version script: - mkdir $CXX-mt && cd $CXX-mt - $CMAKE -DCMAKE_CXX_COMPILER=$CXX -DCLASP_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Wall -Wextra" ../ - make -j3 && make test CTEST_OUTPUT_ON_FAILURE=1 - cd ../ - mkdir $CXX-st && cd $CXX-st - $CMAKE -DCMAKE_CXX_COMPILER=$CXX -DCLASP_BUILD_TESTS=ON -DCLASP_BUILD_WITH_THREADS=OFF -DCMAKE_CXX_FLAGS="-Wall -Wextra" ../ - make -j3 && make test CTEST_OUTPUT_ON_FAILURE=1 - cd ../ clingo-5.2.2/clasp/CHANGES000066400000000000000000001264441320011352300150710ustar00rootroot00000000000000clasp 3.3.3: Sunday, 5th November 2017 * fixed: possible race condition in Windows alarm handling (libpotassco) * fixed: state not fully reset in incremental acyc check * fixed: facade progress state not reset after solving step * fixed: https://github.com/potassco/clasp/issues/11 * fixed: https://github.com/potassco/clasp/issues/13 * https://github.com/potassco/clasp/issues/12 clasp 3.3.2: Saturday, 29th July 2017 * fixed: missing lower bound output in unsat-core optimization for bounds < 0 * fixed: conflict clauses not always tagged with assumptions in unsat-core optimization * fixed: invalid reallocation of vector during theory propagation * fixed: https://github.com/potassco/clingo/issues/45 * fixed: https://github.com/potassco/clasp/issues/10 * added workaround for bug #81365 in gcc 7.1 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81365) * added support for as terminator for minweight constraint in dimacs input clasp 3.3.1: Wednesday, May 3rd 2017 (internal only) * added support for partial checks in clingo propagator clasp 3.3.0: Friday, 28th April 2017 * switched to MIT license * added support for unsatisfiable core shrinking via option "--opt-usc-shrink" * added support for core-guided optimization algorithms K and ONE * CLI changes: - changed syntax of option "--opt-strategy" (old syntax is still supported but deprecated) - First argument selects the overall strategy, i.e. model- or core-guided optimization - Second argument selects the algorithm, e.g. "K" or "OLL" for core-guided optimization - Further arguments enable additional tactics, e.g. "disjoint" for disjoint core preprocessing in core-guided optimization - option "--pre" now prints aspif by default (use "--pre=smodels" for smodels) - merged option "--opt-bound" into "--opt-mode" - merged option "--counter-bump" into "--counter-restarts" - replaced option "--opt-sat" with "--parse-maxsat" - merged option "--dist-mode" into "--distribute" - merged option "--del-protect" into "--update-lbd" - replaced numbers with named constants in various options - added support for specifying bitmask arguments as list of named constants, e.g. "--forget-on-step=varScores,signs,lemmaScores" instead of "--forget-on-step=7" * Integration/clingo: - removed dependency to Intel TBB (multithreading now only uses C++11 threads) - switched to CMake for building clasp - moved libprogram_opts to libpotassco, which is now a submodule of clasp - added support for step-specific true var to simplify implementation of multishot propagators - simplified ClaspFacade solving interface clasp 3.2.3: Monday, 24th April 2017 * fixed: possible crash on Cygwin-32 because of non-increasing wall clock time * fixed: PB constraints not correctly initialized if added on levels > 0 * fixed regression: unsupported atoms in minimize statements not added to program * fixed regression in enum mode "domRec" in case of complementary atoms * fixed spurious backtracking on integrating sat clauses from theory propagator * fixed regression: model heuristic ("--opt-heuristic=2") not applied clasp 3.2.2: Monday, 23rd January 2017 * added experimental support for MiniCard's CNF+ format * added missing stats key "summary.winner" for getting id of winner thread from clingo * fixed regression in sat/pb reader * fixed regression in handling of unsatisfiable optimization problems * fixed regression in component-wise shifting and preprocessing of disjunctive rules * fixed: ClaspFacade::startSolve() could produce duplicate and/or miss models * fixed: failed to handle empty clauses added from theory propagator * fixed: invalid logged lemmas due to buggy minimization in Solver::resolveToFlagged() * fixed: LogicProgram::dispose() must reset pointers * fixed compilation problems on Cygwin and Alpha clasp 3.2.1: Thursday, 13th October 2016 * added support for adding variables from theory propagator * fixed output of "--pre" wrt to externals in incremental setting * fixed regression in projective enumeration in incremental setting * fixed regression in handling of minimize statements containing only zero-weighted literals * fixed possible invalid access to empty input vector in ClaspAppBase::run() * added workaround to fix emcc code-gen bug * fixed type mismatch and warnings when compiled with x64 and _DEBUG * fixed compilation problems on MacOS and ARM clasp 3.2.0: Thursday, 8th September 2016 * added experimental support for new asp format and changed "--pre" option to use it * added propagator for acyclicity constraint (#edge-directive) * added option "--parse-ext" for enabling input extentions: - acyc constraints in smodels, dimacs, and opb format, - objective function in dimacs format, - projection, assumption, output, heuristic directives in dimacs and opb format * added stratification heuristic for weights in core-guided optimization enabled via "--opt-strategy=usc,{8-15}" * added support for parallel solving via C++11 threads instead of Intel TBB (see README) * added ClaspFacade::startSolve() for synchronous (possibly single-threaded) model generation * added option "--vsids-acids" for enabling average conflict-index decision scoring in vsids * added option "--vsids-progress" for enabling Glucose-style decreasing decay scheme * added option "--block-restarts" for enabling Glucose-style blocking of restarts * added option "--del-protect" for enabling Glucose-style temporary freezing of learnt nogods * option "--dom-mod" now also supports modifiers "factor" and "init" and also applies to problems in dimacs and opb format * added support for updating heuristic options in multishot solving (init-moms, score-res, score-other, berk-huang, dom-mod) * added support for config inheritance in portfolio configurations * changed default configuration of tester in disjunctive asp solving * improved handling of extended rules in computation of loop nogoods * improved handling of equivalent and complementary atoms in domain heuristic * option "--nant" now also applies to lookback heuristics * option "--lemma-out" now resolves lemmas to problem variables - added "--lemma-out-dom" for setting variable domain to either input or output - added "--lemma-out-txt" for logging lemmas in ground lp format - added "--lemma-out-max" for limiting number of logged lemmas * replaced "--sign-def=4" with "--sign-def-disj=" for setting default sign of disjunctive atoms * made lower bound updates in parallel optimization lock-free * switched to a more compact representation of input facts in smodels format * replaced old symbol table with simple output list clasp 3.1.5: Friday, 5th August 2016 (updated: 11th August 2016) * fixed: projective enumeration failed to work with option "--no-lookback" * fixed: invalid models in parallel disjunctive solving due to unsynchronized simplifications * fixed: Json output sometimes failed to report correct number of optimal models * fixed: SAT-frontend must retain pure literals for cautious/brave reasoning * fixed: ClaspFacade::start() sometimes failed to reset SharedContext * fixed: Sat-Preprocessor failed to propagate resolution of empty clause * fixed: simplifications after end of incremental step not always propagated to all threads * fixed too strong assertion in eq-preprocessor clasp 3.1.4: Thursday, 10th December 2015 * fixed: "--pre" failed to handle choice/disjunctive heads defined by extended bodies * fixed: "--backprop" failed to backpropagte certain constraints when used with "--eq=0" * fixed: potential deadlock during shutdown/join() in async solving * fixed: DomainHeuristic failed to handle nested heuristic predicates * fixed: invalid delete in DomainHeuristic destructor * fixed: configuration sometimes failed to initialize solver id * rewrote Clause::updateWatch() loop to workaround bug #67892 in gcc 5 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67892) clasp 3.1.3: Friday, 31th July 2015 * fixed: possible livelock in multi-threaded enumeration of optimal models * fixed: parser for _heuristic atoms failed to handle atoms containing strings * fixed: over-satisfied PB constraints not always handled correctly * fixed: incorrect handling of aux vars in Solver::numWatches() * fixed: C++11 isnan issue on Mac clasp 3.1.2: Tuesday, 5th May 2015 * fixed: Option "--heuristic" failed to accept decay factor for domain heuristic * fixed: LogicProgram::getDisjFor() failed to handle hash collisions correctly * fixed: facts in disjunctions not always correctly handled * fixed: domain heuristic failed to distinguish atom names sharing a common prefix * fixed: domain heuristic failed to handle atoms with complementary literals correctly * fixed: LogicProgram::write() must not output gamma rules and/or atoms that are false * fixed regression in handling of sign modifier in domain heuristic * fixed regression in backpropagation during preprocessing clasp 3.1.1: Wednesday, 12th November 2014 * LparseReader now handles "external statement" * fixed: low-level config interface failed to correctly handle successive changes of "opt-bound" * fixed: wrong completition nogoods with option "--no-gamma" * fixed regression in rule simplification (regression in 3.0.x) * fixed regression in "--configuration=jumpy" * fixed regression in handling of modifiers true/false in domain heuristic clasp 3.1.0: Friday, 15th August 2014 * added new strategies for unsatisfiable-core based optimization * added alternative distribution mode via thread-local queues (option " --dist-mode") * generators now propagate top-level assignment to testers * removed optimization options from default configurations * CLI changes: - option "--sat-prepro" now expects the algorithm followed by an optional list of limits - option "--opt-strategy" now takes two arguments; the first mandatory argument selects the major strategy (i.e. branch and bound or unsat-core), while the optional second argument controls fine tuning of said strategy - combined options "--dom-mod" and "--dom-pref" and added enum mode "domRec" for enabling subset optimization via domain heuristic - added "--forget-on-step=2" for discarding previously set variable phases and changed value for discarding nogood activities and learnt nogoods to 4 and 8, respectively - replaced option "--hparam" (and its aliases) with second argument for "--heuristic" - replaced "--berk-once" with more general "--score-res" - renamed option "--number" to "--models" * Integration/clingo: - added support for open (i.e. unassigned) externals - added support for adding constraints via model callback - added low-level interface for accessing a clasp configuration - cleaned up some stats keys and replaced "camelCase" with "snake_case" in keys clasp 3.0.6: Monday, 21st July 2014 * fixed: parallel unsat-core based enumeration of optimal models could skip valid models * fixed: possible race condition in signal handling * fixed: ABA-problem in parallel cb-enumerator could lead to duplicate models (regression in 3.0.x) * fixed: "--share=auto" (default) failed to enable physical sharing in mt-mode (regression in 3.0.x) * fixed: eq over complementary atoms not always correctly handled (regression in 3.0.x) * fixed: incremental domain heuristic failed to apply values to atoms from previous steps * fixed: eq over bodies of size 1 not always correctly handled * fixed: typo in description of "--quiet" clasp 3.0.5: Monday, 19th May 2014 * added support for ThreadTime::getTime() on MacOS X * removed pointless "--del-init" option from config tweety * fixed: non-hcf components not always correctly added in incremental disjunctive programs (clingo) * fixed: empty soft clauses not correctly handled in MaxSAT frontend * fixed: unfounded sets from 2nd level test not always correctly handled * fixed: json output must not print NaN * fixed: asp options not correctly set on configuration update (from clingo) * fixed: regression in handling of (incremental) projection clasp 3.0.4: Thursday, 24th April 2014 * replaced "s SATISFIABLE" with "s UNKNOWN" when called with option "--opt-sat" * improved handling of weight constraints containing incremental assumptions * fixed: typo in output of "--help" * fixed: unsatisfiable-core based optimization sometimes fails to assign all active assumptions * fixed: superfluous rules for facts not always correctly handled * fixed: assigned values for external atoms not always carried over to next step * fixed: clasp sometimes fails on incremental problems if "--lookahead" is used with "--forget-on-step" clasp 3.0.3: Friday, 28th March 2014 * fixed: AsyncResult destructor fails if called after destruction of ClaspFacade * fixed: projective enumeration sometimes fails when used with option "--restart-on-model" * fixed: regression in handling of negative lower bound in optimization clasp 3.0.2: Monday, 17th March 2014 * patch 1 (March 19th, 2014): fixed regression in projective enumeration * added ClaspFacade::startSolveAsync() for enumerating models in an iterator-like fashion * added "--forget-on-step" for simulating iclingo's "--ilearnt" and "--iheuristic" * added "--dom-mod=6" for simulating hclasp's subset minimization * fixed: DefaultUnfoundedCheck sometimes fails with assertion in incremental setting * fixed: wcnf frontend fails if top weight >= 2^31 * fixed: unit cores not always correctly handled in unsatisfiable-core based optimization * fixed: negative lower bound not correctly handled in hierarchical optimization * fixed: projection not correctly handled in incremental setting * fixed: clasp sometimes reports bogus timing values when interrupted via Ctrl-C on Windows * fixed: lookahead fails on non-asp problems if combined with option "--nant" * fixed: wrong/missing models because of incorrect backpropagation with option "--backprop" clasp 3.0.1: Friday, 21th February 2014 * added support for disabling "--opt-bound" via "--opt-bound=no" * added support for passing on/off values for option flags on config update * fixed: multiple occurrences of literal with negative weight not correctly merged (see also: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=739628) * fixed: negative literals not correctly formatted in PB output * fixed: excess bounds in "--opt-bound" not correctly handled * fixed: negatable otions like "[no]-init-moms" not recognized * fixed libprogram_opts: string to long long conversion fails clasp 3.0.0: Friday, 14th February 2014 1. Integrated support for disjunctive solving from claspD-2 2. Integrated domain heuristic from hclasp via option "--heuristic=domain" * added "--dom-pref" and "--dom-mod" for applying domain modifications to certain subsets of atoms 3. Optimization * replaced global "--opt-hierarch" option with more general per thread option "--opt-strategy" to enable competition-based optimization during parallel solving * integrated unsatisfiable-core based optimization from unclasp via "--opt-strategy={4,5}" * replaced "--opt-ignore", "--opt-all", "--opt-best" with option "--opt-mode" and added new reasoning mode for enumerating optimal models via option "--opt-mode=optN" * renamed "--opt-value" to "--opt-bound" 4. Misc * added a new configuration "tweety" and made it the default for asp problems * removed option "--portfolio" in favour of "--configuration=" * added second argument to "--contraction" for replacing long nogoods with decision sequence/all uip clause * added option "--out-hide-aux" for hiding atoms starting with "_" in models * added option "--out-atomf" for setting atom output format * added "--outf=3" for disabling output * simplified deletion options 5. Internals & Integration with clingo * implemented new configuration class * moved option handling and output classes to libclasp * simplified/cleaned up major interfaces * added support for asynchronous solving * added support for incremental/volatile enumeration/optimization * added support for adding/removing aux variables during solving * added low-level interface for accessing statistics clasp 2.1.5: Tuesday, 28th January 2014 * fixed a bug in the handling of unary projection nogoods * fixed a bug in the interplay between lookahead and minimization clasp 2.1.4: Tuesday, 26th November 2013 * fixed a possible crash bug in handling of conditional constraints * fixed a regression in handling of physically shared clauses * fixed compilation issues with clang-500.2.79 on Mac clasp 2.1.3: Friday, 12th April 2013 * fixed a regression in the handling of choice rules in the unfounded set checker clasp 2.1.2: Friday, 5th April 2013 * updated "--outf=1" to ASP-Comp'13 format and added corresponding exit codes * fixed: Wrong/missing models because of incorrect handling of recursive aggregates * fixed: Counter implication restart on root level could introduce an invalid conflict * fixed: clasp does not compile in C++11 mode * fixed regression: Inconsistent behaviour in dimacs front-end when running with or without option "--number=1" clasp 2.1.1: Thursday, 22th November 2012 * fixed regression: MaxSAT-frontend must not assert pure literals / relaxation variables * fixed: spurious warning when using option "--no-lookback" * fixed: "--shuffle" and "--counter-restarts" not working as intended with hierarchical optimization * fixed: Backslashes in JSON output not correctly quoted clasp 2.1.0: Monday, 27th August 2012 * restructured help and revised options and their defaults * added "--help[={1..3}]" for showing basic, advanced, or all options * added "--configuration" for selecting between prefabricated default configurations * revised deletion options and grouped them via common prefix "--del-" * revised thread options and added options for size-/topology-based lemma exchange * added support for dynamic restarts via "--restarts=D," * added "--sign-def" for setting default sign used in decision heuristic * added "--sign-fix" for disabling sign-heuristic * added "--init-moms" for enabling/disabling initialization of heuristic with MOMS-score * added "--fast-exit" for forcing app exit without cleanup * added "--update-act" for enabling LBD-based activity bumping * added "--update-mode" for configuring when update/integrate messages are handled in parallel-search * added "--learn-explicit" to disable usage of implication graph for learnt constraints * added "--share" for configuring physical constraint sharing * added "--init-watches" for controlling initialization of watched literals * added "--counter-restarts" and "--counter-bump" for enabling counter implication restarts * added "--lemma-out-lbd" for restricting lemmas written via "--lemma-out" * added "--lemma-in-lbd" for setting initial lbd of lemmas read via "--lemma-in" * replaced "--loops-in-heu" with more general "--score-other" * replaced "--rand-watches" with more general "--init-watches" * replaced "--initial-lookahead" with "--lookahead=[,]" * replaced "--recursive-str" with "--strengthen=[,]" * replaced "--copy-problem" with more general "--share" * removed options "--brave", "--cautious", "--solution-recording": all superseded by "--enum-mode=" * option "--restarts" now always requires a type; and the "limit" parameter now sets the (initial) length of the sequence * disbaled signal handling during printing of models * fixed: Overflow on parsing large opt-values (issue 3528852) * fixed: Parallel bt-enumerator enumerated duplicate models under certain conditions * fixed: Sat-Preprocessor failed to expand models correctly under very rare conditions * fixed: Erroneous interplay between "otfs=2" and "reverse-arcs" could lead to the unjustified removal of problem constraints * fixed: Incorrect ordering-predicate in MinimizeConstraint could lead to wrong optima * fixed: Solve loop failed to handle restart on total assignment correctly resulting in an infinite loop on some optimization problems * fixed: Duplicate key in JSON-Output of lemma stats clasp 2.0.6: Tuesday, 3rd April 2012 * added better error detection to portfolio parser and fixed a bug in the initialization of thread configs * first attempt at decoupling learnt db growing from restart schedule using independent grow schedule configurable via (hidden) option "--dgrowS" * added "--update-lbd=2" to enable usage of "strict" lbds * added (experimental) support for counter implication restarts and dynamic restarts via hidden options * fixed bugs in code for shared clause integration that could led to unpleasant results ranging from duplicate/missing models in enumeration to crashing if option "--otfs" was used clasp 2.0.5: Sunday, 29th January 2012 * fixed: Input parser for opb and (w)cnf failed to read 64bit integers. * fixed: Outer bound of inner-outer-restarts sometimes remained constant because of integer arithmetic. * fixed: Minimize constraint must not update optimum in enumeration-mode (opt-all). Bug introduced in version 2.0.3 * fixed: Minimize constraint must not update initial (user-set) bound until a model is found. Bug introduced in version 2.0.3 * fixed: Right hand side of minimize constraint not correctly initialized if "--opt-hierarch" was used. * fixed: SharedMinimizeData assumed monotonicity of individual levels - could fail after merging complementary literals in multi-level minimize constraints. Added extra "adjustment"-values to represent values resulting from such merges. clasp 2.0.4: Tuesday, 29th November 2011 * some cleanup in help output * moved general ASP-specific options to separate group * moved "--opt-sat" to basic options * simplified default command-line and made "input-dependent" defaults more explicit * updated interface spec of ProgramBuilder to make it more robust w.r.t incremental update * fixed parsing of "--global-restarts" * fixed: default value for option "--rand-watches" was not applied * fixed: Enumerator did not broadcast last model/optimum of current GP in parallel search * fixed: clauses simplified to binary/ternary are no longer counted twice in stats * fixed: eq-preprocessor sometimes did not reorder head list after merging two bodies * fixed: dimacs front-end failed to read empty dimacs file clasp 2.0.3: Tuesday, 23rd August 2011 * added option "--enum-mode" for setting enumeration algorithm and deprecated superseded options "--solution-recording", "--brave", and "cautious" * made "--enum-mode=record" the default for optimization * added default portfolio settable via "--portfolio=default" * added support for arithmetic restarts * moved "--opt-heuristic" to "Search Options" to allow for different settings in portfolios * fixed: clasp crashes with --pre (issue 3393095) * fixed: value given via "--opt-val" not checked against initial inconsistency * fixed: command line options not applied to portfolio configurations * fixed: parallel enumeration of models did not always respect "--number" * fixed: possible deadlock in parallel hierarchical optimization * fixed: failed to always propagate literals enqueued by PostPropagator::isModel() * fixed: possible crash bug because ReasonStore32::value_type did not decode stored data clasp 2.0.2: Thursday, 30th June 2011 * applied fixes from version 1.3.9 * fixed problem in call to linker (issue 3324430) * fixed a bug in "otfs" which could not handle unsimplified lemmas * fixed a potential invalid memory access in ImplicationList::hasLearnt() * fixed potential underflow in output of solved guiding paths * fixed a problem in UnitHeuristic which failed to handle stop conflicts in parallel solving * fixed various exception-related issues in parallel solving and made it more robust in the face of exceptions * re-enabled optimized unit clause handling for MaxSAT clasp 2.0.1: Wednesday, 27th April 2011 * fixed various (spurious) warnings * updated ProgramOptions to circumvent tellg() bug in g++-4.{4,5,6} under Debian (see also: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=623850) * fixed some issues in build scripts (many thanks to Thomas Krennwallner) * configure.sh no longer sets RPATH unless "--set-rpath" is given * check for libtbb now also works on Mac OS * added code for finding TBB in default paths * fixed argument order in calls to compiler * removed spaces in specification of include/library directories clasp 2.0.0: Thursday, 21st April 2011 1. Support for parallel (multithreaded) solving (requires Intel(R) Threading Building Blocks) * configurable number of threads via option "--threads" * splitting-based search via guiding path and dynamic load-balancing * global restarts via option "--global-restarts" to escape from bad initial splits * competition-based search via freely configurable portfolios (option "--portfolio") * combination of splitting-based and portfolio-based search (option "--force-gp") * configurable lemma exchange via Distributor interface and options "--distribute" and "--integrate" * support for parallel enumeration, optimization, and computation of brave-/cautious consequences 2. Optimization * hierarchical (multi-level) optimization via option "--opt-hierarch=1" * hierarchical optimization with varying step lengths via option "--opt-hierarch={2,3}" * changed switch "--opt-heu" to option "--opt-heuristic={1,2,3}", where * 1: use optimize statements in sign heuristic * 2: use optimize statements in model heuristic * 3: use optimize statements in both sign and model heuristic * changed switch "--opt-all" to option "--opt-all=value"; now enumerates all models with optimize value less than or equal to given value 3. New language front-ends * added support for MaxSAT via optimization (option "--opt-sat") * added support for weighted partial MaxSAT problems in wcnf format * added support for weighted boolean optimization (WBO) problems * added support for non-linear constraints to pseudo-Boolean parser 4. New output handling * option "--outf={0,1,2}" for selecting between (0) default output format, (1) competition output format, and (2) output in JSON format * option "--quiet" now accepts a pair for configuring printing of models and optimize values * added verbosity level 3 to enable printing of progress messages * new (hidden) option "--ifs" for setting separator used when printing models 5. Preprocessing & Learning * added (optional) support for blocked clause elimination to SAT-preprocessor * added option "--reverse-arcs" for ManySAT-like conflict analysis with "reverse arcs" * added option "--otfs" for enabling "on the fly subsumption" * added (optional) support for secondary nogood reduction schedule via option "--dsched" * added option "--dinit=min,max" for limiting initial learnt db size to range [min,max] * added option "--dglue=x" to prevent deletion of nogoods with lbd <= x * added option "--update-lbd" for enabling dynamic updates of lbds of learnt nogoods 6. Internals * reimplemented constraints to enable sharing (and cloning); forced clear distinction between read-only, shared, and thread-local data * separated read-only program dependency graph from thread-local unfounded set checker so that the former can be shared between multiple threads * added SharedContext object for hosting information to be shared between solving threads * added shareable weight constraints * updated clause representation and added a shared clause constraint * splitted binary-/ternary implication graph into shared read-only static and fine-grained lock-protected dynamic part * implemented lock-free MultiQueue as first concrete nogood distributor (passive, global distribution) * implemented linear-time recursive-strengthen algorithm * switched to new version of ProgramOptions library * added support for "tagged" knowledge, i.e. nogoods tagged with an initial assumption * separated local (solver & search related) from global (enumeration & preprocessing) options in ClaspFacade * implemented more cache-efficient left_right_sequence for storing and distinguishing between clause and general watches * added (hidden) option "--dfrac" to set fraction of nogoods to delete on reduction * added new deletion algorithms and hidden option "--dalgo" for selecting between them * added hidden option "--dscore" for selecting between different nogood activity scoring schemes * added (hidden) option "--berk-once" for switching between multiset and set-based scoring in BerkMin clasp 1.3.6: Friday, 19th November 2010 * added missing copyright information to tests and examples * fixed a bug in preprocessing of weight rules where only literals but not their weights were swapped * fixed: lookahead accessed unitialized memory in incremental setting (concerns iclingo only) * fixed: inner-outer restart sequence always used hard-coded grow-factor clasp 1.3.5: Friday, 24th September 2010 * Removed warning for minimization under projection if safe * fixed inconsequent output format in time and statistics output * fixed bug in output of choice rules with empty head * fixed: truth-value of complementary eq-atom not correctly set * fixed: SAT-preprocessor must not reuse clause ids from previous incremental steps clasp 1.3.4: Monday, 14th June 2010 * moved claspre functionality to clasp (run configure with "--with-claspre" to enable it) * added "--search-limit" to limit search to a certain number of conflicts or restarts * calling clasp with "--stats=2" now prints jump statistics * long loop nogoods are now replaced with decision sequence if the latter is considerably shorter * sat-based preprocessing is now again enabled by default if input format is dimacs or OPB * fixed: option "--rand-prob" not always correctly parsed * fixed: lookahead not correctly initialized in incremental setting (only concerns iclingo) * fixed: enumerators not always correctly terminated when solving under assumptions * fixed: sat-output failed to '0'-terminate models * fixed: "--opt-value" did not work with negative numbers * simplified some code to avoid internal compiler error in gcc-3.4.3 clasp 1.3.3: Thursday, 1st April 2010 (April Fools' Day) * added "--trans-ext=card" and "--trans-ext=integ" for transforming cardinality rules resp. extended integrity constraints * added "--lemma-out=" and "--lemma-in=" for writing lemmas to resp. reading lemmas from * clasp now prints suboptimal models in PB-mode if called with "--verbosity=2" * added more timing statistics * application now reports actual average size of learnt lemmas instead of average contracted size * fixed: "--del=no" did not fully disable nogood deletion * fixed: "--opt-value" not checked against initial sum of minimize constraint * fixed: dimacs parser must not assign undefined literals to false if more than one model is requested * fixed: possible double-deletion in option "--pre" * fixed: unfounded set checker sometimes too lazy w.r.t heads of recursive extended rules * fixed a minor bug in eq-preprocessing * changed some code to avoid code generation bug in Visual C++ 2008 x64 see: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=526921 clasp 1.3.2: Friday, 15th January 2010 * fixed a 64-bit portability problem; clasp should now also run under Mac OS X 10.6 * fixed option "--pre" * fixed: SAT-preprocessor not correctly initialized on SAT-problems with more than 4 Mio. clauses clasp 1.3.1: Tuesday, 8th December 2009 * changed some internal interface to simplify integration of clasp in clingo/iclingo/clingcon * fixed a couple of bugs in the eq-preprocessing * fixed a bug in transformation of weight rules in incremental setting * fixed a crash bug in experimental "--backprop" preprocessor * fixed a bug that made clasp exit with code S_UNKNOWN (0) instead of S_UNSAT (20) on unsat problems (computation was correct, though) * fixed a command-line problem: option "--recursive-str" wrongly required an argument * fixed a small problem in PB-frontend that led to wrong optima clasp 1.3.0: Tuesday, 20th October 2009 * added an OPB front-end for solving linear Pseudo-Boolean constraint problems and removed switch "--dimacs": the input format (Smodels-input, dimacs, or OPB) is now automatically detected * added switch "--opt-ignore" and "--opt-heu" for ignoring optimize statements during search, resp. for setting the preferred value of literals occurring in minimize statements to false * added switch "--estimate" for initializing size of learnt DB based on estimated problem complexity * added switch "--reset-restart" for resetting restart schedule after each model found * added switch "--asp09" for enabling ASP'09 competition output format * added switch "--pre" for only printing preprocessed program * added switch "--backprop" for enabling backpropagation in ASP-preprocessor. Note: EXPERIMENTAL FEATURE * added option "--time-limit=" for setting a solving time limit of seconds * added option "--verbose=" for controlling status messages, where "--verbose=0" disables all status messages "--verbose=1" is the default and prints basic status information "--verbose=2" prints more status messages * option "--quiet" no longer controls status messages; it only disables printing of models * replaced option "--lookback=" with switch "--no-lookback" * option "--save-progress" now takes an int to enable progress saving only on jumps >= > 0 * default heuristic now disables MOMs-based top-level heuristic on large problems * removed auto_lookahead option * internal: added better interfaces for users of clasp library (iClingo, Clingcon, ...) * fixed an optimization that violated gcc's strict aliasing rules and could led to crashes * fixed a bug in the interplay of projective enumeration and sat-preprocessing that could led to the enumeration of duplicate models (w.r.t the projection variables) * fixed two bugs w.r.t optimization: first, clasp sometimes reported unknown optimum although last model was optimal. Second, reported optima for minimize statements containing facts were too low (optimality of models was correct, though) * fixed a lookahead bug which occurred only together with sat-preprocessing * fixed a small glitch in the recursive nogood minimization (switch "--recursive-str") clasp 1.2.1: Tuesday, 14th April 2009 * fixed a crash bug in handling of weight rules with bound 0 (introduced in 1.2.0) * added warning for minimization under projection * reverted behaviour of "--number" to pre 1.2.0, i.e. "--number" is again considered during optimization/computation of consequences * removed spurious warning when "--number" is not explicitly set on optimization * disabled printing of cautious consequences and optimization for UNSAT problems * clasp now also prints current optimum on interrupt clasp 1.2.0: Tuesday, 10th March 2009 * added "--project" for enabling projective enumeration * added "--solution-recording" for enabling alternative enumeration mode based on (solution) nogoods * added "--restart-on-model" for restarting search after each model (randomize enumeration) * changed "--initial-lookahead" to "--initial-lookahead=", where gives the number of choices to be selected by lookahead. If 0, lookahead is only used during preprocessing. * removed "--opt-restart", which is now superseded by "--restart-on-model" * added support for minimization during consequence computation * added new (platform specific) timer which won't overflow after merely 36 minutes * improved algorithm for handling recursive weight constraints * fixed a bug where B+ atoms were falsely removed during preprocessing * fixed a crash bug where clasp created bogus minimize statements for trivially UNSAT programs * fixed a bug in the unfounded set checker where multiple SCCs were not always handled correctly (bug was introduced in version 1.1.0) * fixed ProgramBuilder::writeProgram so that it now correctly writes integrity constraints (internal) clasp 1.1.3: Monday, 24th November 2008 * fixed handling of zero weighted atoms in minimize statements * fixed a bug that caused "--deletion=no" to constantly delete all learnt nogoods clasp 1.1.2: Saturday, 25th October 2008 * fixed a bug in the unfounded set checker (bug introduced in version 1.1.0) clasp 1.1.1: Monday, 13th October 2008 * revised option names, help text, and error messages * fixed a bug in the preprocessing/simplification of weight rules * fixed several bugs in the handling of incremental programs clasp 1.1.0: Thursday, 31th July 2008 * added "--sat-prepro" for SatElite-like preprocessing * improved eq-Preprocessing and updated "--eq" to reflect new iterative algorithm * added "--cautious" and "--brave" for cautious resp. brave reasoning * added new optimization mode "--opt-rand": similar to optimize-one but restarts after each enumerated model * added "--local-restarts" for local restarts as described in "Local Restarts" by Ryvchin and Strichman * added new inner-outer restart strategy from PicoSat; quadratic-scheme remains default for now * added "--expensiveccm" for expensive conflict clause minimization a la MiniSat; old Beame-scheme remains default for now * replaced old VSIDS heuristic with MiniSat-like VSIDS heuristic * changed growth strategy of learnt db * changed default value of "--contraction" to 250 * added support for incremental program update (internal) clasp 1.0.5: Monday, 31th December 2007 * added "--minimization=all" for conflict clause minimization over all antecedent types * changed default of "--minimization" from "bin" to "all". * added "--save-progress" for RSat-like progress saving * added "--optimize-value" for setting initial value(s) of optimize function * optimized implementation of cardinality-/weight-rules * simplified and improved implementation of ProgramBuilder and preprocessing * unfounded set checker is now also backtrack-free for extended rules * if "--rand-watches" is not used, watches in clauses are initialized to the two least watched literals * fixed a bug regarding lookahead: if lookahead was not used as heuristic, literal dependencies were not cleared; failed-literal detection skipped literals and thus did not always find all conflicts. * fixed a bug that led to wrong answers/crashes if "loops=no" was used * fixed a bug in preprocessing of minimize rules clasp 1.0.4: Wednesday, 22th August 2007 (updated: 24th August 2007) * improved equivalence-preprocessing w.r.t bodies of size > 1 and slightly decreased memory usage * improved look-back heuristics * changed default value of "--trans-ext" to "no", i.e. extended rules are now handled natively by default * simplified output and added "--stats" for enabling printing of extended statistics * implemented non-recursive version of Tarjan's SCC algorithm to prevent stack overflows on large SCCs * fixed another bug in handling of minimize rules * fixed a bug in the command-line interface that led to a crash when an unknown heuristic was given * fixed a bug concerning preprocessing/simplification of weight rules * 08/24/2007: fixed a bug in preprocessing of cardinality/weight rules containing duplicate literals * 10/25/2007: fixed a bug in preprocessing of satisfied bodies * 10/27/2007: fixed a bug where weight constraints were inadvertently handled as cardinality constraints whenever the second weight equaled 1 * 11/09/2007: fixed a bug in preprocessing of unsupported bodies clasp 1.0.3: Monday, 16th July 2007 * added a new parameter "no" to "--loops" which disables learning of loop formulas * improved performance of the equivalence-preprocessing algorithm on certain inputs * adapted lookahead so that it can distinguish equivalent variables * fixed a bug in the dimacs front-end that led to incorrect results on certain inputs * if "--loops=shared" was used, learnt loop formulas were not added to the learnt db and thus not subject to nogood deletion * fixed a bug that led to an infinite loop on certain optimization problems (bug was introduced in version 1.0.2) * added signal handler to intercept standard signals like SIGTERM clasp 1.0.2: Friday, 15th June 2007 * added "--eq" for equivalence-based preprocessing; added "--eq" to default command line * "--contraction" expects threshold length for dynamic compression of long learnt clauses (default: 60) * added a second (optional) grow factor to "--deletion" that is applied after every reduction * added "--reduce-on-restart" that removes some of the learnt nogoods on every restart * added "--optimize" for computing either one or all optimal solutions * fixed a bug that led to a crash when "--evaluate-loops=false" was used together with the default heuristic * fixed a bug that led to a crash on certain problems when lookahead was used in lookback mode clasp 1.0.1: Wednesday, 28th March 2007 * some fixes to make clasp compile on gcc 4.1 and gcc 4.2 * fixed a bug in the RNG that led to array-out-of-bounds accesses using certain standard library implementations * fixed a bug in the (native) handling of constraint-rules - clasp treated their bodies as sets and spuriously removed duplicate atoms * fixed a bug in the handling of compute-statements - clasp failed to produce a conflict if the compute-statement forced an unsupported atom to be true. clasp 1.0: Wednesday, 7th March 2007 * added native support for extended rules (disabled by default) * added support for optimize statements * added "--dimacs" for reading CNF-problems in dimacs-format * added "--contraction": dynamic clause compression for very long learnt clauses * added "--minimize": (weak) conflict clause minimization * added "--lookahead" for (configurable) failed-literal-detection * added "--rand-watches" for random initialization of watches * added "--rand-prop" for support of occasional random-choices * added "--supp-models" for computation of supported models * added "--bounded-restarts" for allowing (bounded) restarts afer solution was found * new and more dynamic VSIDS heuristic * new smodels-like lookahead heuristic * changed nogood deletion heuristic * removed -s option (replaced with --initial-lookahead) * renamed --no-learn option (now: --lookback=no) clasp Asp-Comp: Revision: Wednesday, 20th December 2006 * scaled-down version for the ASP-competition clasp RC4: Wednesday, 25th October 2006 * added new restart strategies * addad a randomization strategy similar to satzoo's "Burst of random variable orders" * added an option to initialize the random number generator * fixed bug in LparseReader that caused an infinite loop on bad input * fixed implementation of BerkMin heuristic * fixed potential memory-leak in clause deletion code clasp RC3: Friday, 29th September 2006 * transformation of extended rules to normal rules * some low-level stuff to improve performance clasp RC2: Monday, 19th June 2006 * version produced for paper * major bug fixes clasp RC1: Friday, 16th June 2006 * initial version clingo-5.2.2/clasp/CMakeLists.txt000066400000000000000000000122471320011352300166310ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.1) project(CLASP VERSION 3.3.3 LANGUAGES CXX) # Enable folders in IDEs like Visual Studio set_property(GLOBAL PROPERTY USE_FOLDERS ON) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "No build type selected - using 'Release'") set(CMAKE_BUILD_TYPE "Release") endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(GNUInstallDirs) # Configuration options option(CLASP_BUILD_APP "whether or not to build the clasp application" ON) option(CLASP_BUILD_STATIC "whether or not to link statically (if supported)" OFF) option(CLASP_BUILD_TESTS "whether or not to build clasp unit tests" OFF) option(CLASP_BUILD_EXAMPLES "whether or not to build examples" OFF) option(CLASP_BUILD_WITH_THREADS "whether or not to build clasp with threading support (requires C++11)" ON) option(CLASP_INSTALL_LIB "whether or not to install libclasp" OFF) if (NOT MSVC) if (NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) endif() if (NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) endif() if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) endif() else() set(VC_RELEASE_LINK_OPTIONS /LTCG) SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${VC_RELEASE_LINK_OPTIONS}") SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${VC_RELEASE_LINK_OPTIONS}") SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${VC_RELEASE_LINK_OPTIONS}") SET(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} ${VC_RELEASE_LINK_OPTIONS}") if (CLASP_BUILD_STATIC) # force static runtime string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") endif() endif() set(clasp_include_dest "clasp-${CLASP_VERSION}") set(clasp_library_dest "clasp-${CLASP_VERSION}") set(cmake_dest "clasp-${CLASP_VERSION}/cmake") if (CLASP_INSTALL_LIB AND NOT CMAKE_INSTALL_LIBDIR) message(STATUS "LIBDIR no set - using lib") set(CMAKE_INSTALL_LIBDIR lib) endif() # C++11 is required for building with threads if (CLASP_BUILD_WITH_THREADS) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # some versions of findThreads will fail if C is not enabled enable_language(C) find_package(Threads REQUIRED) # Add libatomic if necessary if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_USE_PTHREADS_INIT) include (CheckCXXSourceCompiles) set (OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set (OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) list(APPEND CMAKE_REQUIRED_FLAGS "-std=c++11") list(APPEND CMAKE_REQUIRED_LIBRARIES Threads::Threads) check_cxx_source_compiles(" #include #include std::atomic x (0); int main() { uint64_t i = x.load(std::memory_order_relaxed); return 0; } " CLASP_HAS_WORKING_LIBATOMIC) set (CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) set (CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES}) if (NOT CLASP_HAS_WORKING_LIBATOMIC) check_library_exists(atomic __atomic_fetch_add_4 "" CLASP_HAS_LIBATOMIC) if (CLASP_HAS_LIBATOMIC) set_property(TARGET Threads::Threads APPEND PROPERTY INTERFACE_LINK_LIBRARIES "atomic") endif() endif() endif() endif() # Check for and optionally build external dependency find_package(potassco 1.0 QUIET CONFIG) if (NOT potassco_FOUND) if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libpotassco/CMakeLists.txt) message(STATUS "Potassco is not installed - fetching submodule") execute_process(COMMAND git submodule update --init WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_QUIET) else() message(STATUS "Potassco is not installed - using local copy") endif() set(LIB_POTASSCO_BUILD_APP ${CLASP_BUILD_APP} CACHE BOOL "") set(LIB_POTASSCO_INSTALL_LIB ${CLASP_INSTALL_LIB} CACHE BOOL "") add_subdirectory(libpotassco) endif() # Build clasp library add_subdirectory(src) # Build optional targets if(CLASP_BUILD_TESTS) enable_testing() add_subdirectory(tests) endif() # optional doc target find_package(Doxygen) if(DOXYGEN_FOUND) set(doxyfile "${CMAKE_CURRENT_SOURCE_DIR}/doc/api/clasp.doxy") add_custom_target(doc_clasp COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/doc/api" COMMENT "Generating documentation..." VERBATIM) set_target_properties(doc_clasp PROPERTIES FOLDER doc) endif() if(CLASP_BUILD_APP) add_subdirectory(app) endif() if(CLASP_BUILD_EXAMPLES) add_subdirectory(examples) endif() # Export configure_file(cmake/clasp-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/clasp-config-version.cmake @ONLY) configure_file(cmake/clasp-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/clasp-config.cmake @ONLY) if (CLASP_INSTALL_LIB) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/clasp-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/clasp-config-version.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/${cmake_dest}") install(EXPORT clasp DESTINATION "${CMAKE_INSTALL_LIBDIR}/${cmake_dest}") endif() clingo-5.2.2/clasp/LICENSE000066400000000000000000000020621320011352300150700ustar00rootroot00000000000000clasp Copyright (c) 2015-2017 Benjamin Kaufmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. clingo-5.2.2/clasp/README.md000066400000000000000000000117061320011352300153470ustar00rootroot00000000000000# clasp clasp is an answer set solver for (extended) normal and disjunctive logic programs. It is part of the [Potassco](https://potassco.org) project for *Answer Set Programming* (ASP). The primary algorithm of clasp relies on conflict-driven nogood learning, a technique that proved very successful for satisfiability checking (SAT). clasp has been genuinely developed for answer set solving but can also be applied as a (Max-)SAT or PB solver or as a C++ library in another program. It provides different reasoning modes and other advanced features including: - [Enumeration][enum] and [Optimization][opt] of ([Projected][proj]) Solutions, - Cautious and Brave Reasoning, - [Advanced Disjunctive Solving][claspD2], - [Parallel (multithreaded) solving][claspmt], - [Domain heuristic][hclasp] modifications, - [Unsatisfiable-core based optimization][unclasp], - [ASP/SAT/PB modulo acyclicity][acyc], - Different input formats including [smodels][smodels], [aspif][aspif], [dimacs][dimacs] and [opb][opb]. Detailed information (including a User's manual), source code, and pre-compiled binaries are available at: http://potassco.org/ ## LICENSE clasp is distributed under the MIT License. See LICENSE for details regarding the license. ## PACKAGE CONTENTS LICENSE - The MIT License CHANGES - Major changes between versions README.md - This file CMakeLists.txt - Configuration file for building clasp with CMake cmake/ - Module directory for additional CMake scripts app/ - Source code directory of the command-line interface clasp/ - Header directory of the clasp library src/ - Source code directory of the clasp library tests/ - Unit tests of the clasp library examples/ - Examples using the clasp library libpotassco/ - Directory of the potassco library tools/ - Some additional files ## BUILDING & INSTALLING The preferred way to build clasp is to use [CMake][cmake] version 3.1 or later together with a C++ compiler that supports C++11. The following options can be used to configure the build: CLASP_BUILD_APP : whether or not to build the clasp application CLASP_BUILD_TESTS : whether or not to build clasp unit tests CLASP_BUILD_EXAMPLES : whether or not to build examples CLASP_BUILD_WITH_THREADS: whether or not to build clasp with threading support (requires C++11) For example, to build clasp in release mode in directory ``: cmake -H. -B cmake --build To install clasp afterwards: cmake --build --target install To set the installation prefix, run `cmake` with option `-DCMAKE_INSTALL_PREFIX=`. Finally, you can always skip installation and simply copy the clasp executable to a directory of your choice. ## DOCUMENTATION A User's Guide is available from http://potassco.org/ Source code documentation can be generated with [Doxygen][doxygen]. Either explicitly: cd libclasp/doc/api doxygen clasp.doxy or via the `doc_clasp` target when using cmake. ## USAGE clasp reads problem instances either from stdin, e.g cat problem | clasp or from a given file, e.g clasp problem Type clasp --help to get a basic overview of options supported by clasp or clasp --help={2,3} for a more detailed list. In addition to printing status information, clasp also provides information about the computation via its exit status. The exit status is either one or a combination of: 0 : search was not started because of some option (e.g. '--help') 1 : search was interrupted 10 : problem was found to be satisfiable 20 : problem was proved to be unsatisfiable Exit codes 1 and 11 indicate that search was interrupted before the final result was computed. Exit code 30 indicates that either all models were found (enumeration), optimality was proved (optimization), or all consequences were computed (cautious/brave reasoning). Finally, exit codes greater than 32 are used to signal errors. [enum]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekanesc07c.pdf [proj]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekasc09a.pdf [opt]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekakasc11c.pdf [claspmt]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekasc12b.pdf [claspD2]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekasc13a.pdf [hclasp]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekaotroscwa13a.pdf [unclasp]: http://www.cs.uni-potsdam.de/wv/pdfformat/ankamasc12a.pdf [acyc]: http://www.cs.uni-potsdam.de/wv/pdfformat/bogejakasc15b.pdf [aspif]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekakaosscwa16b.pdf [smodels]: http://www.tcs.hut.fi/Software/smodels/lparse.ps [dimacs]: http://www.satcompetition.org/2009/format-benchmarks2009.html [opb]: http://www.cril.univ-artois.fr/PB09/solver_req.html [doxygen]: http://www.stack.nl/~dimitri/doxygen/ [cmake]: https://cmake.org/ clingo-5.2.2/clasp/app/000077500000000000000000000000001320011352300146435ustar00rootroot00000000000000clingo-5.2.2/clasp/app/CMakeLists.txt000066400000000000000000000015401320011352300174030ustar00rootroot00000000000000set(files clasp_app.cpp clasp_app.h main.cpp) add_executable(clasp ${files}) set_target_properties(clasp PROPERTIES FOLDER exe) if (NOT CMAKE_INSTALL_BINDIR) message(STATUS "BINDIR not set - using bin") set(CMAKE_INSTALL_BINDIR "bin") endif() if (CLASP_BUILD_STATIC AND UNIX AND NOT APPLE) if (CLASP_BUILD_WITH_THREADS) string(CONCAT refs "-Wl,-u,pthread_cancel,-u,pthread_cond_broadcast," "-u,pthread_cond_destroy,-u,pthread_cond_signal," "-u,pthread_cond_timedwait,-u,pthread_cond_wait," "-u,pthread_create,-u,pthread_detach,-u,pthread_join," "-u,pthread_equal") target_link_libraries(clasp ${refs}) endif() target_link_libraries(clasp "-static") endif() target_link_libraries(clasp libclasp) install(TARGETS clasp EXPORT clasp DESTINATION ${CMAKE_INSTALL_BINDIR}) clingo-5.2.2/clasp/app/clasp_app.cpp000066400000000000000000000664001320011352300173170ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #include "clasp_app.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #pragma warning (disable : 4996) #endif #if defined(__GLIBC__) || defined(__GNU_LIBRARY__) #include #if defined(_FPU_EXTENDED) && defined(_FPU_SINGLE) && defined(_FPU_DOUBLE) && defined(_FPU_GETCW) && defined(_FPU_SETCW) #define CLASP_HAS_FPU_CONTROL inline unsigned fpuReset(unsigned m) { _FPU_SETCW(m); return m; } inline unsigned fpuInit() { unsigned r; _FPU_GETCW(r); fpuReset((r & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE); return r; } #endif #elif defined (_MSC_VER) && !defined(_WIN64) #include #define CLASP_HAS_FPU_CONTROL inline unsigned fpuReset(unsigned m) { _controlfp(m, _MCW_PC); return m; } inline unsigned fpuInit() { unsigned r = _controlfp(0, 0); fpuReset(_PC_53); return r; } #pragma fenv_access (on) #endif #if !defined(CLASP_HAS_FPU_CONTROL) inline unsigned fpuReset(unsigned) { return 0u; } inline unsigned fpuInit() { return 0u; } #endif inline bool setFpuMode() { return (sizeof(void*)*CHAR_BIT) < size_t(64u); } namespace Clasp { ///////////////////////////////////////////////////////////////////////////////////////// // Some helpers ///////////////////////////////////////////////////////////////////////////////////////// static double shutdownTime_g; static const std::string stdinStr = "stdin"; static const std::string stdoutStr = "stdout"; inline bool isStdIn(const std::string& in) { return in == "-" || in == stdinStr; } inline bool isStdOut(const std::string& out) { return out == "-" || out == stdoutStr; } ///////////////////////////////////////////////////////////////////////////////////////// // ClaspAppOptions ///////////////////////////////////////////////////////////////////////////////////////// namespace Cli { ClaspAppOptions::ClaspAppOptions() : outf(0), compute(0), ifs(' '), hideAux(false), onlyPre(0), printPort(false) { quiet[0] = quiet[1] = quiet[2] = static_cast(UCHAR_MAX); } void ClaspAppOptions::initOptions(Potassco::ProgramOptions::OptionContext& root) { using namespace Potassco::ProgramOptions; OptionGroup basic("Basic Options"); basic.addOptions() ("print-portfolio,@1", flag(printPort), "Print default portfolio and exit") ("quiet,q" , notify(this, &ClaspAppOptions::mappedOpts)->implicit("2,2,2")->arg(""), "Configure printing of models, costs, and calls\n" " %A: [,][,]\n" " : print {0=all|1=last|2=no} models\n" " : print {0=all|1=last|2=no} optimize values []\n" " : print {0=all|1=last|2=no} call steps [2]") ("pre", notify(this, &ClaspAppOptions::mappedOpts)->arg("")->implicit("aspif"), "Print simplified program and exit\n" " %A: Set output format to {aspif|smodels} (implicit: %I)") ("outf,@1", storeTo(outf)->arg(""), "Use {0=default|1=competition|2=JSON|3=no} output") ("out-atomf,@2" , storeTo(outAtom), "Set atom format string (
?%%0?)")
		("out-ifs,@2"   , notify(this, &ClaspAppOptions::mappedOpts), "Set internal field separator")
		("out-hide-aux,@1" , flag(hideAux), "Hide auxiliary atoms in answers")
		("lemma-in,@1"     , storeTo(lemmaIn)->arg(""), "Read additional lemmas from %A")
		("lemma-out,@1"    , storeTo(lemmaLog)->arg(""), "Log learnt lemmas to %A")
		("lemma-out-lbd,@2", storeTo(lemma.lbdMax)->arg(""), "Only log lemmas with lbd <= %A")
		("lemma-out-max,@2", storeTo(lemma.logMax)->arg(""), "Stop logging after %A lemmas")
		("lemma-out-dom,@2", notify(this, &ClaspAppOptions::mappedOpts), "Log lemmas over  variables")
		("lemma-out-txt,@2", flag(lemma.logText), "Log lemmas as ground integrity constraints")
		("hcc-out,@2", storeTo(hccOut)->arg(""), "Write non-hcf programs to %A.#scc")
		("file,f,@3" , storeTo(input)->composing(), "Input files")
		("compute,@2", storeTo(compute)->arg(""), "Force given literal to true")
	;
	root.add(basic);
}
bool ClaspAppOptions::mappedOpts(ClaspAppOptions* this_, const std::string& name, const std::string& value) {
	if (name == "quiet") {
		const char* err = 0;
		uint32      q[3]= {uint32(UCHAR_MAX),uint32(UCHAR_MAX),uint32(UCHAR_MAX)};
		int      parsed = Potassco::xconvert(value.c_str(), q, &err);
		for (int i = 0; i != parsed; ++i) { this_->quiet[i] = static_cast(q[i]); }
		return parsed && *err == 0;
	}
	else if (name == "out-ifs") {
		if (value.empty() || value.size() > 2) { return false;}
		if (value.size() == 1) { this_->ifs = value[0]; return true; }
		if (value[1] == 't')   { this_->ifs = '\t'; return true; }
		if (value[1] == 'n')   { this_->ifs = '\n'; return true; }
		if (value[1] == 'v')   { this_->ifs = '\v'; return true; }
		if (value[1] == '\\')  { this_->ifs = '\\'; return true; }
	}
	else if (name == "lemma-out-dom") {
		return (this_->lemma.domOut = (strcasecmp(value.c_str(), "output") == 0)) == true || strcasecmp(value.c_str(), "input") == 0;
	}
	else if (name == "pre") {
		if      (strcasecmp(value.c_str(), "aspif")   == 0) { this_->onlyPre = (int8)AspParser::format_aspif; return true; }
		else if (strcasecmp(value.c_str(), "smodels") == 0) { this_->onlyPre = (int8)AspParser::format_smodels; return true; }
	}
	return false;
}
bool ClaspAppOptions::validateOptions(const Potassco::ProgramOptions::ParsedOptions&) {
	if (quiet[1] == static_cast(UCHAR_MAX)) { quiet[1] = quiet[0]; }
	return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
// ClaspAppBase
/////////////////////////////////////////////////////////////////////////////////////////
ClaspAppBase::ClaspAppBase() { }
ClaspAppBase::~ClaspAppBase(){ }
const int* ClaspAppBase::getSignals() const {
	static const int signals[] = {
		SIGINT, SIGTERM
#if !defined (_WIN32)
		, SIGUSR1, SIGUSR2, SIGQUIT, SIGHUP, SIGXCPU, SIGXFSZ
#endif
		, 0};
		return signals;
}
bool ClaspAppBase::parsePositional(const std::string& t, std::string& out) {
	int num;
	if (Potassco::string_cast(t, num)) { out = "number"; }
	else                               { out = "file";   }
	return true;
}
void ClaspAppBase::initOptions(Potassco::ProgramOptions::OptionContext& root) {
	claspConfig_.addOptions(root);
	claspAppOpts_.initOptions(root);
	root.find("verbose")->get()->value()->defaultsTo("1");
}

void ClaspAppBase::validateOptions(const Potassco::ProgramOptions::OptionContext&, const Potassco::ProgramOptions::ParsedOptions& parsed, const Potassco::ProgramOptions::ParsedValues& values) {
	if (claspAppOpts_.printPort) {
		printTemplate();
		exit(E_UNKNOWN);
	}
	setExitCode(E_NO_RUN);
	ProblemType pt = getProblemType();
	POTASSCO_REQUIRE(claspAppOpts_.validateOptions(parsed) && claspConfig_.finalize(parsed, pt, true), "command-line error!");
	ClaspAppOptions& app = claspAppOpts_;
	POTASSCO_REQUIRE(app.lemmaLog.empty() || isStdOut(app.lemmaLog) || (std::find(app.input.begin(), app.input.end(), app.lemmaLog) == app.input.end() && app.lemmaIn != app.lemmaLog),
		"'lemma-out': cowardly refusing to overwrite input file!");
	POTASSCO_REQUIRE(app.lemmaIn.empty() || isStdIn(app.lemmaIn) || std::ifstream(app.lemmaIn.c_str()).is_open(),
		"'lemma-in': could not open file!");
	for (std::size_t i = 1; i < app.input.size(); ++i) {
		POTASSCO_EXPECT(isStdIn(app.input[i]) || std::ifstream(app.input[i].c_str()).is_open(),
			"'%s': could not open input file!", app.input[i].c_str());
	}
	POTASSCO_REQUIRE(!app.onlyPre || pt == Problem_t::Asp, "Option '--pre' only supported for ASP!");
	setExitCode(0);
	storeCommandArgs(values);
}
void ClaspAppBase::setup() {
	ProblemType pt = getProblemType();
	clasp_         = new ClaspFacade();
	if (setFpuMode()) { fpuMode_ = fpuInit(); }
	if (!claspAppOpts_.onlyPre) {
		out_ = createOutput(pt);
		Event::Verbosity verb	= (Event::Verbosity)std::min(verbose(), (uint32)Event::verbosity_max);
		if (out_.get() && out_->verbosity() < (uint32)verb) { verb = (Event::Verbosity)out_->verbosity(); }
		if (!claspAppOpts_.lemmaLog.empty()) {
			logger_ = new LemmaLogger(claspAppOpts_.lemmaLog.c_str(), claspAppOpts_.lemma);
		}
		EventHandler::setVerbosity(Event::subsystem_facade , verb);
		EventHandler::setVerbosity(Event::subsystem_load   , verb);
		EventHandler::setVerbosity(Event::subsystem_prepare, verb);
		EventHandler::setVerbosity(Event::subsystem_solve  , verb);
		clasp_->ctx.setEventHandler(this, logger_.get() == 0 ? SharedContext::report_default : SharedContext::report_conflict);
	}
}

void ClaspAppBase::shutdown() {
	if (!clasp_.get()) { return; }
	if (logger_.get()) { logger_->close(); }
	lemmaIn_ = 0;
	const ClaspFacade::Summary& result = clasp_->shutdown();
	if (shutdownTime_g) {
		shutdownTime_g += RealTime::getTime();
		info(POTASSCO_FORMAT("Shutdown completed in %.3f seconds", shutdownTime_g));
	}
	if (out_.get())  { out_->shutdown(result); }
	setExitCode(getExitCode() | exitCode(result));
	if (setFpuMode()){ fpuReset(fpuMode_); }
}

void ClaspAppBase::run() {
	if (out_.get()) {
		Potassco::Span in = !claspAppOpts_.input.empty() ? Potassco::toSpan(claspAppOpts_.input) : Potassco::toSpan(&stdinStr, 1);
		out_->run(getName(), getVersion(), Potassco::begin(in), Potassco::end(in));
	}
	try        { run(*clasp_); }
	catch(...) {
		try { blockSignals(); setExitCode(E_ERROR); throw; }
		catch (const std::bad_alloc&  ) { setExitCode(E_MEMORY); error("std::bad_alloc"); }
		catch (const std::exception& e) { error(e.what()); }
		catch (...)                     { ; }
	}
}

bool ClaspAppBase::onSignal(int sig) {
	if (!clasp_.get() || !clasp_->interrupt(sig)) {
		info("INTERRUPTED by signal!");
		setExitCode(E_INTERRUPT);
		shutdown();
		exit(getExitCode());
	}
	else {
		// multiple threads are active - shutdown was initiated
		shutdownTime_g = -RealTime::getTime();
		info("Sending shutdown signal...");
	}
	return false; // ignore all future signals
}

void ClaspAppBase::onEvent(const Event& ev) {
	const LogEvent* log = event_cast(ev);
	if (log && log->isWarning()) {
		warn(log->msg);
		return;
	}
	else if (const NewConflictEvent* cfl = event_cast(ev)) {
		if (logger_.get()) { logger_->add(*cfl->solver, *cfl->learnt, cfl->info); }
		return;
	}
	if (out_.get()) {
		blockSignals();
		out_->onEvent(ev);
		unblockSignals(true);
	}
}

bool ClaspAppBase::onModel(const Solver& s, const Model& m) {
	bool ret = true;
	if (out_.get() && !out_->quiet()) {
		blockSignals();
		ret = out_->onModel(s, m);
		unblockSignals(true);
	}
	return ret;
}
bool ClaspAppBase::onUnsat(const Solver& s, const Model& m) {
	bool ret = true;
	if (out_.get() && !out_->quiet()) {
		blockSignals();
		ret = out_->onUnsat(s, m);
		unblockSignals(true);
	}
	return ret;
}

int ClaspAppBase::exitCode(const RunSummary& run) const {
	int ec = 0;
	if (run.sat())               { ec |= E_SAT;       }
	if (run.complete())          { ec |= E_EXHAUST;   }
	if (run.result.interrupted()){ ec |= E_INTERRUPT; }
	return ec;
}

void ClaspAppBase::printTemplate() const {
	printf(
		"# clasp %s configuration file\n"
		"# A configuration file contains a (possibly empty) list of configurations.\n"
		"# Each of which must have the following format:\n"
		"#   [()]: \n"
		"# where  is a string that must not contain ':',\n"
		"#  is one of clasp's default configs (and optional)\n"
		"# and     is a command-line string of clasp options in long-format, e.g.\n"
		"# ('--heuristic=vsids --restarts=L,100').\n"
		"#\n"
		"# SEE: clasp --help\n"
		"#\n"
		"# NOTE: The options '--configuration' and '--tester' must not occur in a\n"
		"#       configuration file. Furthermore, global options are ignored in all\n"
		"#       but the first configuration.\n"
		"#\n"
		"# NOTE: Options given on the command-line are added to all configurations in a\n"
		"#       configuration file. If an option is given both on the command-line and\n"
		"#       in a configuration file, the one from the command-line is preferred.\n"
		"#\n"
		"# NOTE: If, after adding command-line options, a configuration\n"
		"#       contains mutually exclusive options an error is raised.\n"
		"#\n", CLASP_VERSION);
	for (ConfigIter it = ClaspCliConfig::getConfig(Clasp::Cli::config_many); it.valid(); it.next()) {
		printf("%s: %s\n", it.name(), it.args());
	}
}
void ClaspAppBase::printVersion() {
	Potassco::Application::printVersion();
	printLibClaspVersion();
	printLicense();
}
void ClaspAppBase::printLicense() const {
	printf("License: The MIT License \n");
}
void ClaspAppBase::printLibClaspVersion() const {
	printf("libclasp version %s (libpotassco version %s)\n", CLASP_VERSION, LIB_POTASSCO_VERSION);
	printf("Configuration: WITH_THREADS=%d\n", CLASP_HAS_THREADS);
	printf("%s\n", CLASP_LEGAL);
	fflush(stdout);
}

void ClaspAppBase::printHelp(const Potassco::ProgramOptions::OptionContext& root) {
	Potassco::Application::printHelp(root);
	if (root.getActiveDescLevel() >= Potassco::ProgramOptions::desc_level_e1) {
		printf("[asp] %s\n", ClaspCliConfig::getDefaults(Problem_t::Asp));
		printf("[cnf] %s\n", ClaspCliConfig::getDefaults(Problem_t::Sat));
		printf("[opb] %s\n", ClaspCliConfig::getDefaults(Problem_t::Pb));
	}
	if (root.getActiveDescLevel() >= Potassco::ProgramOptions::desc_level_e2) {
		printf("\nDefault configurations:\n");
		printDefaultConfigs();
	}
	else {
		const char* ht3 = "\nType ";
		if (root.getActiveDescLevel() == Potassco::ProgramOptions::desc_level_default) {
			printf("\nType '%s --help=2' for more options and defaults\n", getName());
			ht3 = "and ";
		}
		printf("%s '%s --help=3' for all options and configurations.\n", ht3, getName());
	}
	fflush(stdout);
}
void ClaspAppBase::printConfig(ConfigKey k) const {
	uint32 minW = 2, maxW = 80;
	ConfigIter it = ClaspCliConfig::getConfig(k);
	printf("%s:\n%*c", it.name(), minW-1, ' ');
	const char* opts = it.args();
	for (std::size_t size = std::strlen(opts), n = maxW - minW; n < size;) {
		while (n && opts[n] != ' ') { --n; }
		if (!n) { break; }
		printf("%.*s\n%*c", static_cast(n), opts, static_cast(minW - 1), ' ');
		size -= n + 1;
		opts += n + 1;
		n = (maxW - minW);
	}
	printf("%s\n", opts);
}
void ClaspAppBase::printDefaultConfigs() const {
	for (int i = Clasp::Cli::config_default+1; i != Clasp::Cli::config_default_max_value; ++i) {
		printConfig(static_cast(i));
	}
}
void ClaspAppBase::writeNonHcfs(const PrgDepGraph& graph) const {
	Potassco::StringBuilder buf;
	for (PrgDepGraph::NonHcfIter it = graph.nonHcfBegin(), end = graph.nonHcfEnd(); it != end; ++it) {
		buf.appendFormat(".%u", (*it)->id());
		WriteCnf cnf(claspAppOpts_.hccOut + buf.c_str());
		const SharedContext& ctx = (*it)->ctx();
		cnf.writeHeader(ctx.numVars(), ctx.numConstraints());
		cnf.write(ctx.numVars(), ctx.shortImplications());
		Solver::DBRef db = ctx.master()->constraints();
		for (uint32 i = 0; i != db.size(); ++i) {
			if (ClauseHead* x = db[i]->clause()) { cnf.write(x); }
		}
		for (uint32 i = 0; i != ctx.master()->trail().size(); ++i) {
			cnf.write(ctx.master()->trail()[i]);
		}
		cnf.close();
		buf.clear();
	}
}
std::istream& ClaspAppBase::getStream(bool reopen) const {
	static std::ifstream file;
	static bool isOpen = false;
	if (!isOpen || reopen) {
		file.close();
		isOpen = true;
		if (!claspAppOpts_.input.empty() && !isStdIn(claspAppOpts_.input[0])) {
			file.open(claspAppOpts_.input[0].c_str());
			POTASSCO_EXPECT(file.is_open(), "Can not read from '%s'!", claspAppOpts_.input[0].c_str());
		}
	}
	return file.is_open() ? file : std::cin;
}

// Creates output object suitable for given input format
Output* ClaspAppBase::createOutput(ProblemType f) {
	SingleOwnerPtr out;
	if (claspAppOpts_.outf == ClaspAppOptions::out_none) {
		return 0;
	}
	if (claspAppOpts_.outf != ClaspAppOptions::out_json || claspAppOpts_.onlyPre) {
		TextOutput::Format outFormat = TextOutput::format_asp;
		if      (f == Problem_t::Sat){ outFormat = TextOutput::format_sat09; }
		else if (f == Problem_t::Pb) { outFormat = TextOutput::format_pb09;  }
		else if (f == Problem_t::Asp && claspAppOpts_.outf == ClaspAppOptions::out_comp) {
			outFormat = TextOutput::format_aspcomp;
		}
		out.reset(new TextOutput(verbose(), outFormat, claspAppOpts_.outAtom.c_str(), claspAppOpts_.ifs));
		if (claspConfig_.parse.isEnabled(ParserOptions::parse_maxsat) && f == Problem_t::Sat) {
			static_cast(out.get())->result[TextOutput::res_sat] = "UNKNOWN";
		}
	}
	else {
		out.reset(new JsonOutput(verbose()));
	}
	if (claspAppOpts_.quiet[0] != static_cast(UCHAR_MAX)) {
		out->setModelQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[0]));
	}
	if (claspAppOpts_.quiet[1] != static_cast(UCHAR_MAX)) {
		out->setOptQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[1]));
	}
	if (claspAppOpts_.quiet[2] != static_cast(UCHAR_MAX)) {
		out->setCallQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[2]));
	}
	if (claspAppOpts_.hideAux && clasp_.get()) {
		clasp_->ctx.output.setFilter('_');
	}
	return out.release();
}
void ClaspAppBase::storeCommandArgs(const Potassco::ProgramOptions::ParsedValues&) {
	/* We don't need the values */
}
void ClaspAppBase::handleStartOptions(ClaspFacade& clasp) {
	if (!clasp.incremental()) {
		claspConfig_.releaseOptions();
	}
	if (claspAppOpts_.compute && clasp.program()->type() == Problem_t::Asp) {
		Potassco::Lit_t lit = Potassco::neg(claspAppOpts_.compute);
		static_cast(clasp.program())->addRule(Potassco::Head_t::Disjunctive, Potassco::toSpan(), Potassco::toSpan(&lit, 1));
	}
	if (!claspAppOpts_.lemmaIn.empty()) {
		class LemmaIn : public Potassco::AspifInput {
		public:
			typedef Potassco::AbstractProgram PrgAdapter;
			LemmaIn(const std::string& fn, PrgAdapter* prg) : Potassco::AspifInput(*prg), prg_(prg) {
				if (!isStdIn(fn)) { file_.open(fn.c_str()); }
				POTASSCO_REQUIRE(accept(getStream()), "'lemma-in': invalid input file!");
			}
			~LemmaIn() { delete prg_; }
		private:
			std::istream& getStream() { return file_.is_open() ? file_ : std::cin; }
			PrgAdapter*   prg_;
			std::ifstream file_;
		};
		SingleOwnerPtr prgTemp;
		if (clasp.program()->type() == Problem_t::Asp) { prgTemp = new Asp::LogicProgramAdapter(*static_cast(clasp.program())); }
		else { prgTemp = new BasicProgramAdapter(*clasp.program()); }
		lemmaIn_ = new LemmaIn(claspAppOpts_.lemmaIn, prgTemp.release());
	}
}
bool ClaspAppBase::handlePostGroundOptions(ProgramBuilder& prg) {
	if (!claspAppOpts_.onlyPre) {
		if (lemmaIn_.get()) { lemmaIn_->parse(); }
		if (logger_.get())  { logger_->startStep(prg, clasp_->incremental()); }
		return true;
	}
	prg.endProgram();
	if (prg.type() == Problem_t::Asp) {
		Asp::LogicProgram& asp = static_cast(prg);
		AspParser::Format outf = static_cast(claspAppOpts_.onlyPre);
		if (outf == AspParser::format_smodels && !asp.supportsSmodels()) {
			std::ofstream null;
			try { AspParser::write(asp, null, outf); }
			catch (const std::logic_error& e) {
				error("Option '--pre': unsupported input format!");
				info(std::string(e.what()).append(" in 'smodels' format").c_str());
				info("Try '--pre=aspif' to print in 'aspif' format");
				setExitCode(E_ERROR);
				return false;
			}
		}
		AspParser::write(asp, std::cout, outf);
	}
	else {
		error("Option '--pre': unsupported input format!");
		setExitCode(E_ERROR);
	}
	return false;
}
bool ClaspAppBase::handlePreSolveOptions(ClaspFacade& clasp) {
	if (!claspAppOpts_.hccOut.empty() && clasp.ctx.sccGraph.get()){ writeNonHcfs(*clasp.ctx.sccGraph); }
	return true;
}
void ClaspAppBase::run(ClaspFacade& clasp) {
	clasp.start(claspConfig_, getStream());
	handleStartOptions(clasp);
	while (clasp.read()) {
		if (handlePostGroundOptions(*clasp.program())) {
			clasp.prepare();
			if (handlePreSolveOptions(clasp)) { clasp.solve(); }
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////
// ClaspApp
/////////////////////////////////////////////////////////////////////////////////////////
ClaspApp::ClaspApp() {}

ProblemType ClaspApp::getProblemType() {
	return ClaspFacade::detectProblemType(getStream());
}

void ClaspApp::run(ClaspFacade& clasp) {
	ClaspAppBase::run(clasp);
}

void ClaspApp::printHelp(const Potassco::ProgramOptions::OptionContext& root) {
	ClaspAppBase::printHelp(root);
	printf("\nclasp is part of Potassco: %s\n", "http://potassco.org/clasp");
	printf("Get help/report bugs via : %s\n"  , "http://potassco.org/support\n");
	fflush(stdout);
}
/////////////////////////////////////////////////////////////////////////////////////////
// LemmaLogger
/////////////////////////////////////////////////////////////////////////////////////////
LemmaLogger::LemmaLogger(const std::string& to, const Options& o)
	: str_(isStdOut(to) ? stdout : fopen(to.c_str(), "w"))
	, inputType_(Problem_t::Asp)
	, options_(o)
	, step_(0) {
	POTASSCO_EXPECT(str_, "Could not open lemma log file '%s'!", to.c_str());
}
LemmaLogger::~LemmaLogger() { close(); }
void LemmaLogger::startStep(ProgramBuilder& prg, bool inc) {
	logged_ = 0;
	++step_;
	if (!options_.logText) {
		if (step_ == 1) { fprintf(str_, "asp 1 0 0%s\n", inc ? " incremental" : ""); }
		else            { fprintf(str_, "0\n"); }
	}
	if ((inputType_ = static_cast(prg.type())) == Problem_t::Asp && prg.endProgram()) {
		// create solver variable to potassco literal mapping
		Asp::LogicProgram& asp = static_cast(prg);
		for (Asp::Atom_t a = asp.startAtom(); a != asp.startAuxAtom(); ++a) {
			Literal sLit = asp.getLiteral(a);
			if (sLit.var() >= solver2asp_.size()) {
				solver2asp_.resize(sLit.var() + 1, 0);
			}
			Potassco::Lit_t& p = solver2asp_[sLit.var()];
			if (!p || (!sLit.sign() && p < 0)) {
				p = !sLit.sign() ? Potassco::lit(a) : Potassco::neg(a);
			}
		}
	}
	solver2NameIdx_.clear();
	if (options_.logText && prg.endProgram()) {
		const SharedContext& ctx = *prg.ctx();
		for (OutputTable::pred_iterator beg = ctx.output.pred_begin(), it = beg, end = ctx.output.pred_end(); it != end; ++it) {
			Var v = it->cond.var();
			if (ctx.varInfo(v).output()) {
				if (solver2NameIdx_.size() <= v) { solver2NameIdx_.resize(v + 1, UINT32_MAX); }
				solver2NameIdx_[v] = static_cast(it - beg);
			}
		}
	}
}
void LemmaLogger::add(const Solver& s, const LitVec& cc, const ConstraintInfo& info) {
	LitVec temp;
	const LitVec* out = &cc;
	uint32 lbd = info.lbd();
	if (lbd > options_.lbdMax || logged_ >= options_.logMax) { return; }
	if (info.aux() || options_.domOut || std::find_if(cc.begin(), cc.end(), std::not1(std::bind1st(std::mem_fun(&Solver::inputVar), &s))) != cc.end()) {
		uint8 vf = options_.domOut ? VarInfo::Input|VarInfo::Output : VarInfo::Input;
		if (!s.resolveToFlagged(cc, vf, temp, lbd) || lbd > options_.lbdMax) { return; }
		out = &temp;
	}
	char buffer[1024];
	Potassco::StringBuilder str(buffer, sizeof(buffer), Potassco::StringBuilder::Dynamic);
	if (options_.logText) { formatText(*out, s.sharedContext()->output, lbd, str); }
	else                  { formatAspif(*out, lbd, str); }
	fwrite(str.c_str(), sizeof(char), str.size(), str_);
	++logged_;
}
void LemmaLogger::formatAspif(const LitVec& cc, uint32, Potassco::StringBuilder& out) const {
	out.appendFormat("1 0 0 0 %u", (uint32)cc.size());
	for (LitVec::const_iterator it = cc.begin(), end = cc.end(); it != end; ++it) {
		Literal sLit = ~*it; // clause -> constraint
		Potassco::Lit_t a = toInt(sLit);
		if (inputType_ == Problem_t::Asp) {
			a = sLit.var() < solver2asp_.size() ? solver2asp_[sLit.var()] : 0;
			if (!a) { return; }
			if (sLit.sign() != (a < 0)) { a = -a; }
		}
		out.appendFormat(" %d", a);
	}
	out.append("\n");
}
void LemmaLogger::formatText(const LitVec& cc, const OutputTable& tab, uint32 lbd, Potassco::StringBuilder& out) const {
	out.append(":-");
	const char* sep = " ";
	for (LitVec::const_iterator it = cc.begin(), end = cc.end(); it != end; ++it) {
		Literal sLit = ~*it; // clause -> constraint
		uint32 idx = sLit.var() < solver2NameIdx_.size() ? solver2NameIdx_[sLit.var()] : UINT32_MAX;
		if (idx != UINT32_MAX) {
			const OutputTable::PredType& p = *(tab.pred_begin() + idx);
			assert(sLit.var() == p.cond.var());
			out.appendFormat("%s%s%s", sep, sLit.sign() != p.cond.sign() ? "not " : "", p.name.c_str());
		}
		else {
			if (inputType_ == Problem_t::Asp) {
				Potassco::Lit_t a = sLit.var() < solver2asp_.size() ? solver2asp_[sLit.var()] : 0;
				if (!a) { return; }
				if (sLit.sign() != (a < 0)) { a = -a; }
				sLit = Literal(Potassco::atom(a), a < 0);
			}
			out.appendFormat("%s%s__atom(%u)", sep, sLit.sign() ? "not " : "", sLit.var());
		}
		sep = ", ";
	}
	out.appendFormat(".  %%lbd = %u\n", lbd);
}
void LemmaLogger::close() {
	if (!str_) { return; }
	if (!options_.logText) { fprintf(str_, "0\n"); }
	fflush(str_);
	if (str_ != stdout) { fclose(str_); }
	str_ = 0;
	solver2asp_.clear();
}
/////////////////////////////////////////////////////////////////////////////////////////
// WriteCnf
/////////////////////////////////////////////////////////////////////////////////////////
WriteCnf::WriteCnf(const std::string& outFile) : str_(fopen(outFile.c_str(), "w")) {
	POTASSCO_EXPECT(str_, "Could not open cnf file '%s'!", outFile.c_str());
}
WriteCnf::~WriteCnf() { close(); }
void WriteCnf::writeHeader(uint32 numVars, uint32 numCons) {
	fprintf(str_, "p cnf %u %u\n", numVars, numCons);
}
void WriteCnf::write(ClauseHead* h) {
	lits_.clear();
	h->toLits(lits_);
	for (LitVec::const_iterator it = lits_.begin(), end = lits_.end(); it != end; ++it) {
		fprintf(str_, "%d ", toInt(*it));
	}
	fprintf(str_, "%d\n", 0);
}
void WriteCnf::write(Var maxVar, const ShortImplicationsGraph& g) {
	for (Var v = 1; v <= maxVar; ++v) {
		g.forEach(posLit(v), *this);
		g.forEach(negLit(v), *this);
	}
}
void WriteCnf::write(Literal u) {
	fprintf(str_, "%d 0\n", toInt(u));
}
bool WriteCnf::unary(Literal p, Literal x) const {
	return p.rep() >= x.rep() || fprintf(str_, "%d %d 0\n", toInt(~p), toInt(x)) > 0;
}
bool WriteCnf::binary(Literal p, Literal x, Literal y) const {
	return p.rep() >= x.rep() || p.rep() >= y.rep() || fprintf(str_, "%d %d %d 0\n", toInt(~p), toInt(x), toInt(y)) > 0;
}
void WriteCnf::close() {
	if (str_) {
		fflush(str_);
		fclose(str_);
		str_ = 0;
	}
}

}} // end of namespace Clasp::Cli

clingo-5.2.2/clasp/app/clasp_app.h000066400000000000000000000235671320011352300167730ustar00rootroot00000000000000//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#ifndef CLASP_CLASP_APP_H_INCLUDED
#define CLASP_CLASP_APP_H_INCLUDED

#ifdef _MSC_VER
#pragma once
#endif
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
namespace Potassco { class StringBuilder; }
namespace Clasp { namespace Cli {
/////////////////////////////////////////////////////////////////////////////////////////
// clasp exit codes
/////////////////////////////////////////////////////////////////////////////////////////
enum ExitCode {
	E_UNKNOWN   = 0,  /*!< Satisfiablity of problem not knwon; search not started.    */
	E_INTERRUPT = 1,  /*!< Run was interrupted.                                       */
	E_SAT       = 10, /*!< At least one model was found.                              */
	E_EXHAUST   = 20, /*!< Search-space was completely examined.                      */
	E_MEMORY    = 33, /*!< Run was interrupted by out of memory exception.            */
	E_ERROR     = 65, /*!< Run was interrupted by internal error.                     */
	E_NO_RUN    = 128 /*!< Search not started because of syntax or command line error.*/
};
/////////////////////////////////////////////////////////////////////////////////////////
// clasp app helpers
/////////////////////////////////////////////////////////////////////////////////////////
class WriteCnf {
public:
	WriteCnf(const std::string& outFile);
	~WriteCnf();
	void writeHeader(uint32 numVars, uint32 numCons);
	void write(Var maxVar, const ShortImplicationsGraph& g);
	void write(ClauseHead* h);
	void write(Literal unit);
	void close();
	bool unary(Literal, Literal) const;
	bool binary(Literal, Literal, Literal) const;
private:
	WriteCnf(const WriteCnf&);
	WriteCnf& operator=(const WriteCnf&);
	FILE*  str_;
	LitVec lits_;
};
class LemmaLogger {
public:
	struct Options {
		Options() : logMax(UINT32_MAX), lbdMax(UINT32_MAX), domOut(false), logText(false) {}
		uint32 logMax;  // log at most logMax lemmas
		uint32 lbdMax;  // only log lemmas with lbd <= lbdMax
		bool   domOut;  // only log lemmas that can be expressed over out variables
		bool   logText; // log lemmas in ground lp format
	};
	LemmaLogger(const std::string& outFile, const Options& opts);
	~LemmaLogger();
	void startStep(ProgramBuilder& prg, bool inc);
	void add(const Solver& s, const LitVec& cc, const ConstraintInfo& info);
	void close();
private:
	typedef PodVector::type Var2Idx;
	typedef Atomic_t::type Counter;
	LemmaLogger(const LemmaLogger&);
	LemmaLogger& operator=(const LemmaLogger&);
	void formatAspif(const LitVec& cc, uint32 lbd, Potassco::StringBuilder& out)  const;
	void formatText(const LitVec& cc, const OutputTable& tab, uint32 lbd, Potassco::StringBuilder& out) const;
	FILE*            str_;
	Potassco::LitVec solver2asp_;
	Var2Idx          solver2NameIdx_;
	ProblemType      inputType_;
	Options          options_;
	int              step_;
	Counter          logged_;
};
/////////////////////////////////////////////////////////////////////////////////////////
// clasp specific application options
/////////////////////////////////////////////////////////////////////////////////////////
struct ClaspAppOptions {
	typedef LemmaLogger::Options LogOptions;
	ClaspAppOptions();
	typedef std::vector  StringSeq;
	static bool mappedOpts(ClaspAppOptions*, const std::string&, const std::string&);
	void initOptions(Potassco::ProgramOptions::OptionContext& root);
	bool validateOptions(const Potassco::ProgramOptions::ParsedOptions& parsed);
	StringSeq   input;     // list of input files - only first used!
	std::string lemmaLog;  // optional file name for writing learnt lemmas
	std::string lemmaIn;   // optional file name for reading learnt lemmas
	std::string hccOut;    // optional file name for writing scc programs
	std::string outAtom;   // optional format string for atoms
	uint32      outf;      // output format
	int         compute;   // force literal compute to true
	LogOptions  lemma;     // options for lemma logging
	char        ifs;       // output field separator
	bool        hideAux;   // output aux atoms?
	uint8       quiet[3];  // configure printing of models, optimization values, and call steps
	int8        onlyPre;   // run preprocessor and exit
	bool        printPort; // print portfolio and exit
	enum OutputFormat { out_def = 0, out_comp = 1, out_json = 2, out_none = 3 };
};
/////////////////////////////////////////////////////////////////////////////////////////
// clasp application base
/////////////////////////////////////////////////////////////////////////////////////////
// Base class for applications using the clasp library.
class ClaspAppBase : public Potassco::Application, public Clasp::EventHandler {
public:
	typedef ClaspFacade::Summary  RunSummary;
	typedef Potassco::ProgramOptions::PosOption PosOption;
protected:
	using Potassco::Application::run;
	ClaspAppBase();
	~ClaspAppBase();
	// -------------------------------------------------------------------------------------------
	// Functions to be implemented by subclasses
	virtual ProblemType   getProblemType()             = 0;
	virtual void          run(ClaspFacade& clasp)      = 0;
	virtual Output*       createOutput(ProblemType f);
	virtual void          storeCommandArgs(const Potassco::ProgramOptions::ParsedValues& values);
	// -------------------------------------------------------------------------------------------
	// Helper functions that subclasses might call during run
	void handleStartOptions(ClaspFacade& clasp);
	bool handlePostGroundOptions(ProgramBuilder& prg);
	bool handlePreSolveOptions(ClaspFacade& clasp);
	// -------------------------------------------------------------------------------------------
	// Application functions
	virtual const int*  getSignals()    const;
	virtual HelpOpt     getHelpOption() const { return HelpOpt("Print {1=basic|2=more|3=full} help and exit", 3); }
	virtual PosOption   getPositional() const { return parsePositional; }
	virtual void        initOptions(Potassco::ProgramOptions::OptionContext& root);
	virtual void        validateOptions(const Potassco::ProgramOptions::OptionContext& root, const Potassco::ProgramOptions::ParsedOptions& parsed, const Potassco::ProgramOptions::ParsedValues& values);
	virtual void        setup();
	virtual void        run();
	virtual void        shutdown();
	virtual bool        onSignal(int);
	virtual void        printHelp(const Potassco::ProgramOptions::OptionContext& root);
	virtual void        printVersion();
	static  bool        parsePositional(const std::string& s, std::string& out);
	// -------------------------------------------------------------------------------------------
	// Event handler
	virtual void onEvent(const Event& ev);
	virtual bool onModel(const Solver& s, const Model& m);
	virtual bool onUnsat(const Solver& s, const Model& m);
	// -------------------------------------------------------------------------------------------
	// Status information & output
	int  exitCode(const RunSummary& sol)    const;
	void printTemplate()                    const;
	void printDefaultConfigs()              const;
	void printConfig(ConfigKey k)           const;
	void printLibClaspVersion()             const;
	void printLicense()                     const;
	std::istream& getStream(bool reopen = false) const;
	// -------------------------------------------------------------------------------------------
	// Functions called in handlePreSolveOptions()
	void writeNonHcfs(const PrgDepGraph& graph) const;
	typedef Potassco::ProgramReader     LemmaReader;
	typedef SingleOwnerPtr      OutPtr;
	typedef SingleOwnerPtr ClaspPtr;
	typedef SingleOwnerPtr LogPtr;
	typedef SingleOwnerPtr LemmaPtr;
	ClaspCliConfig  claspConfig_;
	ClaspAppOptions claspAppOpts_;
	ClaspPtr        clasp_;
	OutPtr          out_;
	LogPtr          logger_;
	LemmaPtr        lemmaIn_;
	unsigned        fpuMode_;
};
/////////////////////////////////////////////////////////////////////////////////////////
// clasp application
/////////////////////////////////////////////////////////////////////////////////////////
// Standalone clasp application.
class ClaspApp : public ClaspAppBase {
public:
	ClaspApp();
	const char* getName()       const { return "clasp"; }
	const char* getVersion()    const { return CLASP_VERSION; }
	const char* getUsage()      const {
		return
			"[number] [options] [file]\n"
			"Compute at most  models (0=all) of the instance given in ";
	}
protected:
	virtual ProblemType getProblemType();
	virtual void        run(ClaspFacade& clasp);
	virtual void        printHelp(const Potassco::ProgramOptions::OptionContext& root);
private:
	ClaspApp(const ClaspApp&);
	ClaspApp& operator=(const ClaspApp&);
};
}}
#endif
clingo-5.2.2/clasp/app/main.cpp000066400000000000000000000042161320011352300162760ustar00rootroot00000000000000//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#include "clasp_app.h"
/////////////////////////////////////////////////////////////////////////////////////////
// main - entry point
/////////////////////////////////////////////////////////////////////////////////////////
// #define CHECK_HEAP
#if defined (_MSC_VER) && defined(CHECK_HEAP) && _MSC_VER >= 1200
#include 
#endif
int main(int argc, char** argv) {
#if defined (_MSC_VER) && defined (CHECK_HEAP) && _MSC_VER >= 1200
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) |
	               CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF |
	               _CRTDBG_CHECK_ALWAYS_DF);

	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
	_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
	_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
	_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
	_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
	_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
#endif
	Clasp::Cli::ClaspApp app;
	return app.main(argc, argv);
}
clingo-5.2.2/clasp/clasp/000077500000000000000000000000001320011352300151655ustar00rootroot00000000000000clingo-5.2.2/clasp/clasp/asp_preprocessor.h000066400000000000000000000120001320011352300207200ustar00rootroot00000000000000//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//

#ifndef CLASP_PREPROCESSOR_H_INCLUDED
#define CLASP_PREPROCESSOR_H_INCLUDED

#ifdef _MSC_VER
#pragma once
#endif
#include 
#include 
namespace Clasp { namespace Asp {

/**
 * \addtogroup asp
 */
//@{

//! Preprocesses (i.e. simplifies) a logic program.
/*!
 * Preprocesses (i.e. simplifies) a logic program and associates variables with
 * the nodes of the simplified logic program.
 */
class Preprocessor {
public:
	Preprocessor() : prg_(0), dfs_(true) {}
	//! Possible eq-preprocessing types.
	enum EqType {
		no_eq,    //!< No eq-preprocessing, associate a new var with each supported atom and body.
		full_eq   //!< Check for all kinds of equivalences between atoms and bodies.
	};

	const LogicProgram* program() const  { return prg_; }
	      LogicProgram* program()        { return prg_; }

	//! Starts preprocessing of the logic program.
	/*!
	 * Computes the maximum consequences of prg and associates a variable
	 * with each supported atom and body.
	 * \param prg The logic program to preprocess.
	 * \param t   Type of eq-preprocessing.
	 * \param maxIters If t == full_eq, maximal number of iterations during eq preprocessing.
	 * \param dfs If t == full_eq, classify in df-order (true) or bf-order (false).
	 */
	bool preprocess(LogicProgram& prg, EqType t, uint32 maxIters, bool dfs = true) {
		prg_  = &prg;
		dfs_  = dfs;
		type_ = t;
		return t == full_eq
			? preprocessEq(maxIters)
			: preprocessSimple();
	}

	bool eq() const { return type_ == full_eq; }
	Var  getRootAtom(Literal p) const { return p.id() < litToNode_.size() ? litToNode_[p.id()] : varMax; }
	void setRootAtom(Literal p, uint32 atomId) {
		if (p.id() >= litToNode_.size()) litToNode_.resize(p.id()+1, varMax);
		litToNode_[p.id()] = atomId;
	}
private:
	Preprocessor(const Preprocessor&);
	Preprocessor& operator=(const Preprocessor&);
	bool    preprocessEq(uint32 maxIters);
	bool    preprocessSimple();
	// ------------------------------------------------------------------------
	typedef PrgHead* const *             HeadIter;
	typedef std::pair HeadRange;
	// Eq-Preprocessing
	struct BodyExtra {
		BodyExtra() : known(0), mBody(0), bSeen(0) {}
		uint32 known  :30;  // Number of predecessors already classified, only used for bodies
		uint32 mBody  : 1;  // A flag for marking bodies
		uint32 bSeen  : 1;  // First time we see this body?
	};
	bool     classifyProgram(const VarVec& supportedBodies);
	ValueRep simplifyClassifiedProgram(const HeadRange& atoms, bool more, VarVec& supported);
	PrgBody* addBodyVar(uint32 bodyId);
	bool     addHeadsToUpper(PrgBody* body);
	bool     addHeadToUpper(PrgHead* head, PrgEdge support);
	bool     propagateAtomVar(PrgAtom*, PrgEdge source);
	bool     propagateAtomValue(PrgAtom*, ValueRep val, PrgEdge source);
	bool     mergeEqBodies(PrgBody* b, Var rootId, bool equalLits);
	bool     hasRootLiteral(PrgBody* b) const;
	bool     superfluous(PrgBody* b) const;
	ValueRep simplifyHead(PrgHead* h, bool reclassify);
	ValueRep simplifyBody(PrgBody* b, bool reclassify, VarVec& supported);
	uint32   nextBodyId(VarVec::size_type& idx) {
		if (follow_.empty() || idx == follow_.size()) { return varMax; }
		if (dfs_) {
			uint32 id = follow_.back();
			follow_.pop_back();
			return id;
		}
		return follow_[idx++];;
	}
	// ------------------------------------------------------------------------
	typedef PodVector::type BodyData;
	LogicProgram* prg_;      // program to preprocess
	VarVec        follow_;   // bodies yet to classify
	BodyData      bodyInfo_; // information about the program nodes
	VarVec        litToNode_;// the roots of our equivalence classes
	uint32        pass_;     // current iteration number
	uint32        maxPass_;  // force stop after maxPass_ iterations
	EqType        type_;     // type of eq-preprocessing
	bool          dfs_;      // classify bodies in DF or BF order
};
//@}
} }
#endif

clingo-5.2.2/clasp/clasp/cb_enumerator.h000066400000000000000000000045011320011352300201630ustar00rootroot00000000000000//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#ifndef CLASP_CB_ENUMERATOR_H
#define CLASP_CB_ENUMERATOR_H

#ifdef _MSC_VER
#pragma once
#endif

#include 

namespace Clasp {

//! Enumerator for computing the brave/cautious consequences of a logic program.
/*!
 * \ingroup enumerator
 */
class CBConsequences : public Enumerator {
public:
	enum Type {
		Brave    = Model::Brave,
		Cautious = Model::Cautious,
	};
	enum Algo { Default, Query };
	/*!
	 * \param type Type of consequences to compute.
	 * \param a Type of algorithm to apply if type is Cautious.
	 */
	explicit CBConsequences(Type type, Algo a = Default);
	~CBConsequences();
	int  modelType() const { return type_; }
	bool exhaustive()const { return true; }
	bool supportsSplitting(const SharedContext& problem) const;
	int  unsatType() const;
private:
	class  CBFinder;
	class  QueryFinder;
	class  SharedConstraint;
	ConPtr doInit(SharedContext& ctx, SharedMinimizeData* m, int numModels);
	void   addLit(SharedContext& ctx, Literal p);
	void   addCurrent(Solver& s, LitVec& con, ValueVec& m, uint32 rootL = 0);
	LitVec            cons_;
	SharedConstraint* shared_;
	Type              type_;
	Algo              algo_;
};

}
#endif
clingo-5.2.2/clasp/clasp/clasp_facade.h000066400000000000000000000454241320011352300177340ustar00rootroot00000000000000//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#ifndef CLASP_CLASP_FACADE_H_INCLUDED
#define CLASP_CLASP_FACADE_H_INCLUDED
#ifdef _MSC_VER
#pragma once
#endif

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#if CLASP_HAS_THREADS
#include 
namespace Clasp {
	//! Options for controlling enumeration and solving.
	struct SolveOptions : Clasp::mt::ParallelSolveOptions, EnumOptions {};
}
#else
namespace Clasp {
	struct SolveOptions : Clasp::BasicSolveOptions, EnumOptions {};
}
#endif

/*!
 * \file
 * \brief High-level API
 *
 * This file provides a facade around the clasp library.
 * I.e. a simplified interface for (multishot) solving a problem using
 * some configuration (set of parameters).
 * \ingroup facade
 */
namespace Clasp {
/////////////////////////////////////////////////////////////////////////////////////////
// Configuration
/////////////////////////////////////////////////////////////////////////////////////////
/*!
 * \defgroup facade Facade
 * \brief Simplified interface for (multishot) solving.
 *
 * @{
 */
//! Configuration object for configuring solving via the ClaspFacade.
class ClaspConfig : public BasicSatConfig {
public:
	//! Interface for injecting user-provided post propagators.
	class Configurator {
	public:
		virtual ~Configurator();
		virtual void prepare(SharedContext&);
		virtual bool addPost(Solver& s) = 0;
	};
	typedef BasicSatConfig UserConfig;
	typedef Solver**       SolverIt;
	typedef Asp::LogicProgram::AspOptions AspOptions;
	ClaspConfig();
	~ClaspConfig();
	// Base interface
	void           prepare(SharedContext&);
	void           reset();
	Configuration* config(const char*);
	//! Adds an unfounded set checker to the given solver if necessary.
	/*!
	 * If asp.suppMod is false and the problem in s is a non-tight asp-problem,
	 * the function adds an unfounded set checker to s.
	 */
	bool           addPost(Solver& s) const;
	// own interface
	UserConfig*    testerConfig() const { return tester_; }
	UserConfig*    addTesterConfig();
	//! Registers c as additional callback for when addPost() is called.
	/*!
	 * \param c         Additional configuration to apply.
	 * \param ownership If Ownership_t::Acquire, ownership of c is transferred to the configuration object.
	 * \param once      Whether c should be called once in the first step or also in each subsequent step.
	 */
	void           addConfigurator(Configurator* c, Ownership_t::Type ownership = Ownership_t::Retain, bool once = true);
	SolveOptions   solve; /*!< Options for solve algorithm and enumerator. */
	AspOptions     asp;   /*!< Options for asp preprocessing.      */
	ParserOptions  parse; /*!< Options for input parser. */
private:
	struct Impl;
	ClaspConfig(const ClaspConfig&);
	ClaspConfig& operator=(const ClaspConfig&);
	UserConfig* tester_;
	Impl*       impl_;
};
/////////////////////////////////////////////////////////////////////////////////////////
// ClaspFacade
/////////////////////////////////////////////////////////////////////////////////////////
//! Result of a solving step.
struct SolveResult {
	//! Possible solving results.
	enum Base {
		UNKNOWN  = 0, //!< Satisfiability unknown - a given solve limit was hit.
		SAT      = 1, //!< Problem is satisfiable (a model was found).
		UNSAT    = 2, //!< Problem is unsatisfiable.
	};
	//! Additional flags applicable to a solve result.
	enum Ext {
		EXT_EXHAUST  = 4, //!< Search space is exhausted.
		EXT_INTERRUPT= 8, //!< The run was interrupted from outside.
	};
	bool sat()        const { return *this == SAT; }
	bool unsat()      const { return *this == UNSAT; }
	bool unknown()    const { return *this == UNKNOWN; }
	bool exhausted()  const { return (flags & EXT_EXHAUST)   != 0; }
	bool interrupted()const { return (flags & EXT_INTERRUPT) != 0; }
	operator Base()   const { return static_cast(flags & 3u);}
	uint8 flags;  //!< Set of Base and Ext flags.
	uint8 signal; //!< Term signal or 0.
};

//! A bitmask type for representing supported solve modes.
struct SolveMode_t {
	//! Named constants.
	POTASSCO_ENUM_CONSTANTS(SolveMode_t,
		Default = 0, /**< Solve synchronously in current thread. */
		Async   = 1, /**< Solve asynchronously in worker thread. */
		Yield   = 2, /**< Yield models one by one via handle.    */
		AsyncYield);
	friend inline SolveMode_t operator|(SolveMode_t::E x, SolveMode_t::E y) { return SolveMode_t(static_cast(x)|static_cast(y)); }
	friend inline SolveMode_t operator|(SolveMode_t x, SolveMode_t::E y)    { return SolveMode_t(static_cast(x)|static_cast(y)); }
	friend inline SolveMode_t operator|(SolveMode_t::E x, SolveMode_t y)    { return SolveMode_t(static_cast(x)|static_cast(y)); }
};
//! Provides a simplified interface to the services of the clasp library.
class ClaspFacade : public ModelHandler {
	struct SolveData;
	struct SolveStrategy;
public:
	//! A handle to a possibly asynchronously computed SolveResult.
	class SolveHandle {
	public:
		typedef SolveResult  Result;
		typedef const Model* ModelRef;
		explicit SolveHandle(SolveStrategy*);
		SolveHandle(const SolveHandle&);
		~SolveHandle();
		SolveHandle& operator=(SolveHandle temp)             { swap(*this, temp); return *this; }
		friend void swap(SolveHandle& lhs, SolveHandle& rhs) { std::swap(lhs.strat_, rhs.strat_); }
		/*!
		 * \name Blocking functions
		 * @{ */
		//! Waits until a result is ready and returns it.
		Result   get()              const;
		//! Waits until a result is ready and returns it if it is a model.
		/*!
		 * \note If the corresponding solve operation was not started with
		 * SolveMode_t::Yield, the function always returns 0.
		 * \note A call to resume() invalidates the returned model and starts
		 * the search for the next model.
		 */
		ModelRef model()            const;
		//! Waits until a result is ready.
		void     wait()             const;
		//! Waits for a result but for at most sec seconds.
		bool     waitFor(double sec)const;
		//! Tries to cancel the active operation.
		void     cancel()           const;
		//! Behaves like resume() followed by return model() != 0.
		bool     next()             const;
		//@}
		/*!
		 * \name Non-blocking functions
		 * @{ */
		//! Tests whether a result is ready.
		bool     ready()            const;
		//! Tests whether the operation was interrupted and if so returns the interruption signal.
		int      interrupted()      const;
		//! Tests whether a result is ready and has a stored exception.
		bool     error()            const;
		//! Tests whether the operation is still active.
		bool     running()          const;
		//! Releases ownership of the active model and schedules search for the next model.
		void     resume()           const;
		//@}
	private:
		SolveStrategy* strat_;
	};
	typedef SolveResult Result;
	typedef Potassco::AbstractStatistics AbstractStatistics;
	//! Type summarizing one or more solving steps.
	struct Summary {
		typedef const ClaspFacade* FacadePtr;
		void init(ClaspFacade& f);
		//! Logic program elements added in the current step or 0 if not an asp problem.
		const Asp::LpStats*  lpStep()       const;
		//! Logic program stats or 0 if not an asp problem.
		const Asp::LpStats*  lpStats()      const;
		//! Active problem.
		const SharedContext& ctx()          const { return facade->ctx; }
		/*!
		 * \name Result functions
		 * Solve and enumeration result - not accumulated.
		 * @{
		 */
		bool                 sat()          const { return result.sat(); }
		bool                 unsat()        const { return result.unsat(); }
		bool                 complete()     const { return result.exhausted(); }
		bool                 optimum()      const { return costs() && (complete() || model()->opt); }
		const Model*         model()        const;
		const char*          consequences() const; /**< Cautious/brave reasoning active? */
		bool                 optimize()     const; /**< Optimization active? */
		const SumVec*        costs()        const; /**< Models have associated costs? */
		uint64               optimal()      const; /**< Number of optimal models found. */
		bool                 hasLower()     const;
		SumVec               lower()        const;
		//@}
		//! Visits this summary object.
		void accept(StatsVisitor& out) const;
		FacadePtr facade;    //!< Facade object of this run.
		double    totalTime; //!< Total wall clock time.
		double    cpuTime;   //!< Total cpu time.
		double    solveTime; //!< Wall clock time for solving.
		double    unsatTime; //!< Wall clock time to prove unsat.
		double    satTime;   //!< Wall clock time to first model.
		uint64    numEnum;   //!< Total models enumerated.
		uint64    numOptimal;//!< Optimal models enumerated.
		uint32    step;      //!< Step number (multishot solving).
		Result    result;    //!< Result of step.
	};
	ClaspFacade();
	~ClaspFacade();

	/*!
	 * \name Query functions
	 * Functions for checking the state of this object.
	 * @{ */
	//! Returns whether the problem is still valid.
	bool               ok()                  const { return program() ? program()->ok() : ctx.ok(); }
	//! Returns whether the active step is ready for solving.
	bool               prepared()            const;
	//! Returns whether the active step is currently being solved.
	bool               solving()             const;
	//! Returns whether the active step has been solved, i.e., has a result.
	bool               solved()              const;
	//! Returns whether solving of the active step was interrupted.
	bool               interrupted()         const;
	//! Returns the summary of the active step.
	const Summary&     summary()             const { return step_; }
	//! Returns the summary of the active (accu = false) or all steps.
	const Summary&     summary(bool accu)    const;
	//! Returns solving statistics or throws std::logic_error if solving() is true.
	AbstractStatistics*getStats()            const;
	//! Returns the active configuration.
	const ClaspConfig* config()              const { return config_;}
	//! Returns the current solving step (starts at 0).
	int                step()                const { return (int)step_.step;}
	//! Returns the result of the active step (unknown if run is not yet completed).
	Result             result()              const { return step_.result; }
	//! Returns the active program or 0 if it was already released.
	ProgramBuilder*    program()             const { return builder_.get(); }
	//! Returns whether program updates are enabled.
	bool               incremental()         const;
	//! Returns the active enumerator or 0 if there is none.
	Enumerator*        enumerator()          const;
	//@}

	//! Event type used to signal that a new step has started.
	struct StepStart : Event_t {
		explicit StepStart(const ClaspFacade& f) : Event_t(subsystem_facade, verbosity_quiet), facade(&f) {}
		const ClaspFacade* facade;
	};
	//! Event type used to signal that a solve step has terminated.
	struct StepReady : Event_t {
		explicit StepReady(const Summary& x) : Event_t(subsystem_facade, verbosity_quiet), summary(&x) {}
		const Summary* summary;
	};

	SharedContext ctx; //!< Context-object used to store problem.

	/*!
	 * \name Start functions
	 * Functions for defining a problem.
	 * Calling one of the start functions discards any previous problem
	 * and emits a StepStart event.
	 * @{ */
	//! Starts definition of an ASP-problem.
	Asp::LogicProgram& startAsp(ClaspConfig& config, bool enableProgramUpdates = false);
	//! Starts definition of a SAT-problem.
	SatBuilder&        startSat(ClaspConfig& config);
	//! Starts definition of a PB-problem.
	PBBuilder&         startPB(ClaspConfig& config);
	//! Starts definition of a problem of type t.
	ProgramBuilder&    start(ClaspConfig& config, ProblemType t);
	//! Starts definition of a problem given in stream.
	ProgramBuilder&    start(ClaspConfig& config, std::istream& stream);
	//! Enables support for program updates if supported by the program.
	/*!
	 * \pre program() != 0 and not prepared().
	 * \return true if program updates are supported. Otherwise, false.
	 */
	bool               enableProgramUpdates();
	//! Enables support for (asynchronous) solve interrupts.
	void               enableSolveInterrupts();
	//! Tries to detect the problem type from the given input stream.
	static ProblemType detectProblemType(std::istream& str);
	//! Tries to read the next program part from the stream passed to start().
	/*!
	 * \return false if nothing was read because the stream is exhausted, solving was interrupted,
	 * or the problem is unconditionally unsat.
	 */
	bool               read();
	//@}


	/*!
	 * \name Solve functions
	 * Functions for solving a problem.
	 * @{ */

	enum EnumMode  { enum_volatile, enum_static };

	//! Finishes the definition of a problem and prepares it for solving.
	/*!
	 * \pre !solving()
	 * \post prepared() || !ok()
	 * \param m Mode to be used for handling enumeration-related knowledge.
	 *          If m is enum_volatile, enumeration knowledge is learnt under an
	 *          assumption that is retracted on program update. Otherwise,
	 *          no special assumption is used and enumeration-related knowledge
	 *          might become unretractable.
	 * \note If solved() is true, prepare() first starts a new solving step.
	 */
	void               prepare(EnumMode m = enum_volatile);

	//! Solves the current problem.
	/*!
	 * If prepared() is false, the function first calls prepare() to prepare the problem for solving.
	 * \pre !solving()
	 * \post solved()
	 * \param a A list of unit-assumptions under which solving should operate.
	 * \param eh An optional event handler that is notified on each model and
	 *           once the solve operation has completed.
	 */
	Result             solve(const LitVec& a = LitVec(), EventHandler* eh = 0);
	Result             solve(EventHandler* eh) { return solve(LitVec(), eh); }

	//! Solves the current problem using the given solve mode.
	/*!
	 * If prepared() is false, the function first calls prepare() to prepare the problem for solving.
	 * \pre !solving()
	 * \param mode The solve mode to use.
	 * \param a A list of unit-assumptions under which solving should operate.
	 * \param eh An optional event handler that is notified on each model and
	 *           once the solve operation has completed.
	 * \throws std::logic_error   if mode contains SolveMode_t::Async but thread support is disabled.
	 * \throws std::runtime_error if mode contains SolveMode_t::Async but solve is unable to start a thread.
	 *
	 * \note If mode contains SolveMode_t::Async, the optional event handler is notified in the
	 *       context of the asynchronous thread.
	 *
	 * \note If mode contains SolveMode_t::Yield, models are signaled one by one via the
	 *       returned handle object.
	 *       It is the caller's responsibility to finish the solve operation,
	 *       either by extracting models until SolveHandle::model() returns 0, or
	 *       by calling SolveHandle::cancel().
	 *
	 * To iterate over models one by one use a loop like:
	 * \code
	 * SolveMode_t p = ...
	 * for (auto it = facade.solve(p|SolveMode_t::Yield); it.model(); it.resume()) {
	 *   printModel(*it.model());
	 * }
	 * \endcode
	 */
	SolveHandle        solve(SolveMode_t mode, const LitVec& a = LitVec(), EventHandler* eh = 0);

	//! Tries to interrupt the active solve operation.
	/*!
	 * The function sends the given signal to the active solve operation.
	 * If no solve operation is active (i.e. solving() is false), the signal
	 * is queued and applied to the next solve operation.
	 *
	 * \param sig The signal to raise or 0, to re-raises a previously queued signal.
	 * \return false if no operation was interrupted, because
	 *         there is no active solve operation,
	 *         or the operation does not support interrupts,
	 *         or sig was 0 and there was no queued signal.
	 *
	 * \see enableSolveInterrupts()
	 */
	bool               interrupt(int sig);

	//! Forces termination of the current solving step.
	/*!
	 * \post solved()
	 * \return summary(true)
	 */
	const Summary&     shutdown();

	//! Starts update of the active problem.
	/*!
	 * \pre solving() is false and program updates are enabled (incremental() is true).
	 * \post !solved()
	 * \param updateConfig If true, the function applies any configuration changes.
	 * \param sigQ An action to be performed for any queued signal.
	 *        The default is to apply the signal to the next solve operation, while
	 *        SIGN_IGN can be used to discard queued signals.
	 */
	ProgramBuilder&    update(bool updateConfig, void (*sigQ)(int));
	ProgramBuilder&    update(bool updateConfig = false);
	//@}
private:
	struct Statistics;
	typedef SingleOwnerPtr BuilderPtr;
	typedef SingleOwnerPtr      SolvePtr;
	typedef SingleOwnerPtr        SummaryPtr;
	typedef SingleOwnerPtr     StatsPtr;
	void   init(ClaspConfig& cfg, bool discardProblem);
	void   initBuilder(ProgramBuilder* in);
	bool   isAsp() const { return program() && type_ == Problem_t::Asp; }
	void   discardProblem();
	void   startStep(uint32 num);
	Result stopStep(int signal, bool complete);
	void   updateStats();
	bool   onModel(const Solver& s, const Model& m);
	void   doUpdate(ProgramBuilder* p, bool updateConfig, void (*sig)(int));
	ProblemType  type_;
	Summary      step_;
	LitVec       assume_;
	ClaspConfig* config_;
	BuilderPtr   builder_;
	SummaryPtr   accu_;
	StatsPtr     stats_; // statistics: only if requested
	SolvePtr     solve_; // NOTE: last so that it is destroyed first;
};

/**
 * \example example2.cpp
 * This is an example of how to use the ClaspFacade class for basic solving.
 *
 * \example example3.cpp
 * This is an example of how to use the ClaspFacade class for generator-based solving.
 */

//!@}

}
#endif
clingo-5.2.2/clasp/clasp/claspfwd.h000066400000000000000000000044621320011352300171470ustar00rootroot00000000000000//
// Copyright (c) 2013-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#ifndef CLASP_CLASP_FWD_H_INCLUDED
#define CLASP_CLASP_FWD_H_INCLUDED
/*!
 * \file
 * \brief Forward declarations of important clasp and potassco types.
 */

namespace Potassco {
class TheoryAtom;
class TheoryTerm;
class TheoryData;
template  struct Span;
struct Heuristic_t;
class BufferedStream;
class AbstractStatistics;
}
//! Root namespace for all types and functions of libclasp.
namespace Clasp {
class SharedContext;
class MinimizeBuilder;
class SharedMinimizeData;
class Configuration;
class Constraint;
class ConstraintInfo;
class Solver;
struct Model;
//! Supported problem types.
struct Problem_t {
	enum Type {Sat = 0, Pb = 1, Asp = 2};
};
typedef Problem_t::Type ProblemType;
class ProgramBuilder;
class ProgramParser;
class SatBuilder;
class PBBuilder;
class ExtDepGraph;
class ConstString;
typedef Potassco::Span StrView;
typedef Potassco::Heuristic_t DomModType;
//! Namespace for types and functions used to define ASP programs.
namespace Asp {
class LogicProgram;
class Preprocessor;
class LpStats;
class PrgAtom;
class PrgBody;
class PrgDisj;
class PrgHead;
class PrgNode;
class PrgDepGraph;
struct PrgEdge;
}}

#endif
clingo-5.2.2/clasp/clasp/clause.h000066400000000000000000000547131320011352300166240ustar00rootroot00000000000000//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#ifndef CLASP_CLAUSE_H_INCLUDED
#define CLASP_CLAUSE_H_INCLUDED

#ifdef _MSC_VER
#pragma once
#endif

#include 
namespace Clasp {

//! An array of literals that can be shared between threads.
/*!
 * \ingroup shared_con
 */
class SharedLiterals {
public:
	//! Creates a shareable (ref-counted) object containing the literals in lits.
	/*!
	 * \note The reference count is set to numRefs.
	 */
	static SharedLiterals* newShareable(const LitVec& lits, ConstraintType t, uint32 numRefs = 1) {
		return newShareable(!lits.empty() ? &lits[0]:0, static_cast(lits.size()), t, numRefs);
	}
	static SharedLiterals* newShareable(const Literal* lits, uint32 size, ConstraintType t, uint32 numRefs = 1);

	//! Returns a pointer to the beginning of the literal array.
	const Literal* begin() const { return lits_; }
	//! Returns a pointer to the end of the literal array.
	const Literal* end()   const { return lits_+size(); }
	//! Returns the number of literals in the array.
	uint32         size()  const { return size_type_ >> 2; }
	//! Returns the type of constraint from which the literals originated.
	ConstraintType type()  const { return ConstraintType( size_type_ & uint32(3) ); }
	//! Simplifies the literals w.r.t to the assignment in s.
	/*!
	 * Returns the number of non-false literals in this object or 0 if
	 * the array contains a true literal.
	 * \note If the object is currently not shared, simplify() removes
	 * all false literals from the array.
	 */
	uint32 simplify(Solver& s);

	void            release() { release(1); }
	void            release(uint32 numRefs);
  SharedLiterals* share();
	bool            unique()   const { return refCount_ <= 1; }
	uint32          refCount() const { return refCount_; }
private:
	void destroy();
	SharedLiterals(const Literal* lits, uint32 size, ConstraintType t, uint32 numRefs);
	SharedLiterals(const SharedLiterals&);
	SharedLiterals& operator=(const SharedLiterals&);
	typedef Clasp::Atomic_t::type RCType;
	RCType  refCount_;
	uint32  size_type_;
POTASSCO_WARNING_BEGIN_RELAXED
	Literal lits_[0];
POTASSCO_WARNING_END_RELAXED
};

//! A helper-class for creating/adding clauses.
/*!
 * \ingroup constraint
 * This class simplifies clause creation. It hides the special handling of
 * short, and shared clauses. It also makes sure that learnt clauses watch
 * the literals from the highest decision levels.
 */
class ClauseCreator {
public:
	typedef ConstraintInfo ClauseInfo;
	//! Creates a new ClauseCreator object.
	/*!
	 * \param s the Solver in which to store created clauses.
	 */
	explicit ClauseCreator(Solver* s = 0);
	//! Sets the solver in which created clauses are stored.
	void setSolver(Solver& s)         { solver_ = &s; }
	//! Adds additional flags to be applied in end().
	void addDefaultFlags(uint32 f)    { flags_ |= f; }
	//! Reserve space for a clause of size s.
	void reserve(LitVec::size_type s) { literals_.reserve(s); }
	//! Discards the current clause.
	void clear()                      { literals_.clear(); }

	//! Status of a clause.
	/*!
	 * For a clause with literals [l1,...,ln], status is one of:
	 */
	enum Status {
		// BASE STATUS
		status_open         = 0,  //!< Clause is neither sat, unsat, or unit.
		status_sat          = 1,  //!< At least one literal is true.
		status_unsat        = 2,  //!< All literals are false.
		status_unit         = 4,  //!< All but one literal false.
		// COMPLEX STATUS
		status_sat_asserting= 5,  //!< Sat but literal is implied on lower dl.
		status_asserting    = 6,  //!< Unsat but literal is implied on second highest dl.
		status_subsumed     = 9,  //!< Sat and one literal is true on level 0.
		status_empty        = 10, //!< Unsat and all literals are false on level 0.
	};
	//! A type for storing the result of a clause insertion operation.
	struct Result {
		explicit Result(ClauseHead* loc = 0, Status st = status_open)
			: local(loc)
			, status(st) {}
		ClauseHead*     local;
		Status          status;
		//! Returns false is clause is conflicting w.r.t current assignment.
		bool     ok()   const { return (status & status_unsat) == 0; }
		//! Returns true if the clause implies a literal (possibly after backtracking).
		bool     unit() const { return (status & status_unit) != 0; }
		operator bool() const { return ok(); }
	};
	//! Starts the creation of a new clause.
	/*!
	 * \pre s.decisionLevel() == 0 || t != Constraint_t::Static
	 */
	ClauseCreator& start(ConstraintType t = Constraint_t::Static);
	//! Sets the initial activity of the clause under construction.
	ClauseCreator& setActivity(uint32 a)      { extra_.setActivity(a);  return *this; }
	//! Sets the initial literal block distance of the clause under construction.
	ClauseCreator& setLbd(uint32 lbd)         { extra_.setLbd(lbd); return *this; }
	//! Adds the literal p to the clause under construction.
	ClauseCreator& add(const Literal& p)      { literals_.push_back(p); return *this; }
	//! Removes subsumed lits and orders first lits w.r.t watch order.
	ClauseRep      prepare(bool fullSimplify);
	//! Returns the current size of the clause under construction.
	uint32         size()    const { return (uint32)literals_.size(); }
	//! Returns the literal at the given idx.
	Literal&       operator[](uint32 i)       { return literals_[i]; }
	Literal        operator[](uint32 i) const { return literals_[i]; }
	//! Returns the literals of the clause under construction.
	const LitVec&  lits()    const { return literals_; }
	LitVec&        lits()          { return literals_; }
	//! Returns the clause's type.
	ConstraintType type()    const { return extra_.type(); }
	//! Returns the aux info of the clause under construction.
	ConstraintInfo info()    const { return extra_; }
	//! Creates a new clause object for the clause under construction.
	/*!
	 * \pre The clause does not contain duplicate/complementary literals or
	 *      flags contains clause_force_simplify.
	 *
	 * \note If the clause to be added is empty, end() fails and s.hasConflict() is set to true.
	 * \see Result ClauseCreator::create(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info);
	 */
	Result end(uint32 flags = clause_not_sat | clause_not_conflict);

	/*!
	 * \name Factory functions
	 * Functions for creating and integrating clauses.
	 */
	//@{
	//! Flags controlling clause creation and integration.
	enum CreateFlag {
		// REPRESENTATION
		clause_no_add        = 1,  //!< Do not add clause to solver db.
		clause_explicit      = 2,  //!< Force creation of explicit clause even if size <= 3.
		// STATUS
		clause_not_sat       = 4,  //!< Do not add clause if it is satisfied (but not asserting) w.r.t current assignment.
		clause_not_root_sat  = 8,  //!< Do not add clause if it is satisfied w.r.t the root assignment.
		clause_not_conflict  = 16, //!< Do not add clause if it is conflicting w.r.t the current assignment.
		// INTEGRATE
		clause_no_release    = 32, //!< Do not call release on shared literals.
		clause_int_lbd       = 64, //!< Compute lbd when integrating asserting clauses.
		// PREPARE
		clause_no_prepare    = 128,//!< Assume clause is already ordered w.r.t watches.
		clause_force_simplify= 256,//!< Call simplify() on create.
		clause_no_heuristic  = 512,//!< Do not notify heuristic about new clause.
		// WATCH MODE - only for problem clauses
		clause_watch_first   =1024,//!< Watch first free literals.
		clause_watch_rand    =2048,//!< Watch rand literals.
		clause_watch_least   =4096,//!< Watch least watched literals.
	};
	//! Returns the status of the given clause w.r.t s.
	static Status    status(const Solver& s, const Literal* clause_begin, const Literal* clause_end);
	static Status    status(const Solver& s, const ClauseRep& c);

	//! Returns an abstraction of p's decision level that can be used to order literals.
	/*!
	 * The function returns a value, s.th
	 * order(any true literal) > order(any free literal) > order(any false literal).
	 * Furthermore, for equally assigned literals p and q, order(p) > order(q), iff
	 * level(p) > level(q).
	 */
	static uint32    watchOrder(const Solver& s, Literal p);

	//! Prepares the clause given in lits.
	/*!
	 * A prepared clause [l1...ln] with n >= 2 is a clause that,
	 *  - does not contain any duplicate or complementary literals, and
	 *  - does not contain any subsumed literals (i.e. literals assigned on decision level 0), and
	 *  - is partially ordered w.r.t watchOrder(), i.e., watchOrder(l1) >= watchOrder(l2), and there
	 *    is no lj, j > 2, s.th. watchOrder(lj) > watchOrder(l2)
	 *  .
	 *
	 * Removes subsumed literals from lits and reorders lits s.th.
	 * the first literals are valid watches. Furthermore,
	 * if flags contains clause_force_simplify,
	 * duplicate literals are removed from lits and tautologies are
	 * replaced with the single literal True.
	 */
	static ClauseRep prepare(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info = ClauseInfo());

	//! Creates a clause from the literals given in lits.
	/*!
	 * \param s     The solver to which the clause should be added.
	 * \param lits  The literals of the clause.
	 * \param flags Flag set controlling creation (see ClauseCreator::CreateFlag).
	 * \param info  Initial information (e.g. type) for the new clause.
	 *
	 * \pre !s.hasConflict() and s.decisionLevel() == 0 or extra.learnt()
	 * \pre lits is fully prepared or flags contains suitable prepare flags.
	 *
	 * \note
	 *   If the given clause is unit (or asserting), the unit-resulting literal is
	 *   asserted on the (numerical) lowest level possible but the new information
	 *   is not immediately propagated, i.e. on return queueSize() may be greater than 0.
	 *
	 * \note
	 *   The local representation of the clause is always attached to the solver
	 *   but only added to the solver if clause_no_add is not contained in flags.
	 *   Otherwise, the returned clause is owned by the caller
	 *   and it is the caller's responsibility to manage it. Furthermore,
	 *   learnt statistics are *not* updated automatically in that case.
	 *
	 * \see prepare()
	 */
	static Result create(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info = ClauseInfo());

	/*!
	 * \overload
	 */
	static Result create(Solver& s, const ClauseRep& rep, uint32 flags);

	//! Integrates the given clause into the current search of s.
	/*!
	 * \pre the assignment in s is not conflicting
	 * \param s      The solver in which the clause should be integrated.
	 * \param clause The clause to be integrated.
	 * \param flags  A set of flags controlling integration (see ClauseCreator::CreateFlag).
	 * \param t      Constraint type to use for the local representation.
	 *
	 * \note
	 *   The function behaves similar to ClauseCreator::create() with the exception that
	 *   it does not add local representations for implicit clauses (i.e. size <= 3)
	 *   unless flags contains clause_explicit.
	 *   In that case, an explicit representation is created.
	 *   Implicit representations can only be created via ClauseCreator::create().
	 *
	 * \note
	 *   The function acts as a sink for the given clause (i.e. it decreases its reference count)
	 *   unless flags contains clause_no_release.
	 *
	 * \note integrate() is intended to be called in a post propagator.
	 *   To integrate a set of clauses F, one would use a loop like this:
	 *   \code
	 *   bool MyPostProp::propagate(Solver& s) {
	 *     bool r = true;
	 *     while (!F.empty() && r) {
	 *       SharedLiterals* C = f.pop();
	 *       r = integrate(s, C, ...).ok;
	 *     }
	 *     return r;
	 *   \endcode
	 */
	static Result integrate(Solver& s, SharedLiterals* clause, uint32 flags, ConstraintType t);

	/*!
	 * \overload
	 */
	static Result integrate(Solver& s, SharedLiterals* clause, uint32 flags);
	//@}
private:
	static ClauseRep   prepare(Solver& s, const Literal* in, uint32 inSize, const ClauseInfo& e, uint32 flags, Literal* out, uint32 outMax = UINT32_MAX);
	static Result      create_prepared(Solver& s, const ClauseRep& pc, uint32 flags);
	static ClauseHead* newProblemClause(Solver& s, const ClauseRep& clause, uint32 flags);
	static ClauseHead* newLearntClause(Solver& s, const ClauseRep& clause, uint32 flags);
	static ClauseHead* newUnshared(Solver& s, SharedLiterals* clause, const Literal* w, const ClauseInfo& e);
	static bool        ignoreClause(const Solver& s, const ClauseRep& cl, Status st, uint32 modeFlags);
	Solver*    solver_;   // solver in which new clauses are stored
	LitVec     literals_; // literals of the new clause
	ClauseInfo extra_;    // extra info
	uint32     flags_;    // default flags to be used in end()
};

//! Class for representing a clause in a solver.
/*!
 * \ingroup constraint
 */
class Clause : public ClauseHead {
public:
	typedef Constraint::PropResult PropResult;

	//! Allocates memory for storing a (learnt) clause with nLits literals.
	static void* alloc(Solver& s, uint32 mLits, bool learnt);

	//! Creates a new clause from the clause given in rep.
	/*!
	 * \param s   Solver in which the new clause is to be used.
	 * \param rep The raw representation of the clause.
	 *
	 * \pre The clause given in lits is prepared and contains at least two literals.
	 * \note The clause must be destroyed using Clause::destroy.
	 * \see ClauseCreator::prepare()
	 */
	static ClauseHead*  newClause(Solver& s, const ClauseRep& rep) {
		return newClause(alloc(s, rep.size, rep.info.learnt()), s, rep);
	}
	//! Creates a new clause object in mem.
	/*!
	 * \pre mem points to a memory block that was allocated via Clause::alloc().
	 */
	static ClauseHead*  newClause(void* mem, Solver& s, const ClauseRep& rep);

	//! Creates a new contracted clause from the clause given in rep.
	/*!
	 * A contracted clause consists of an active head and a tail of false literals.
	 * Propagation is restricted to the head.
	 * The tail is only needed to compute reasons from assignments.
	 *
	 * \param s       Solver in which the new clause is to be used.
	 * \param rep     The raw representation of the clause.
	 * \param tailPos The starting index of the tail (first literal that should be temporarily removed from the clause).
	 * \param extend  Extend head part of clause as tail literals become free?
	 */
	static ClauseHead*  newContractedClause(Solver& s, const ClauseRep& rep, uint32 tailPos, bool extend);

	//! Creates a new local surrogate for shared_lits to be used in the given solver.
	/*!
	 * \param s      The solver in which this clause will be used.
	 * \param lits   The shared literals of this clause.
	 * \param e      Initial meta data for the new (local) clause.
	 * \param head   Watches and cache literal for the new (local) clause.
	 * \param addRef Increment ref count of lits.
	 */
	static ClauseHead* newShared(Solver& s, SharedLiterals* lits, const InfoType& e, const Literal head[3], bool addRef = true);

	// Constraint-Interface

	Constraint* cloneAttach(Solver& other);

	/*!
	 * For a clause [x y p] the reason for p is ~x and ~y.
	 * \pre *this previously asserted p
	 * \note if the clause is a learnt clause, calling reason increases
	 * the clause's activity.
	 */
	void reason(Solver& s, Literal p, LitVec& lits);

	bool minimize(Solver& m, Literal p, CCMinRecursive* r);

	bool isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN);

	//! Returns true if clause is SAT.
	/*!
	 * Removes from the clause all literals that are false.
	 */
	bool simplify(Solver& s, bool = false);

	//! Destroys the clause and frees its memory.
	void destroy(Solver* s = 0, bool detach = false);

	// LearntConstraint interface

	//! Returns type() if the clause is currently not satisfied and t.inSet(type()).
	uint32 isOpen(const Solver& s, const TypeSet& t, LitVec& freeLits);

	// clause interface
	BoolPair strengthen(Solver& s, Literal p, bool allowToShort);
	void     detach(Solver&);
	uint32   size()                 const;
	void     toLits(LitVec& out)    const;
	bool     contracted()           const;
	bool     isSmall()              const;
	bool     strengthened()         const;
	uint32   computeAllocSize()     const;
private:
	Clause(Solver& s, const ClauseRep& rep, uint32 tail = UINT32_MAX, bool extend = false);
	Clause(Solver& s, const Clause& other);
	typedef std::pair LitRange;
	void     undoLevel(Solver& s);
	bool     updateWatch(Solver& s, uint32 pos);
	Literal* end() { return head_+local_.size(); }
	Literal* removeFromTail(Solver& s, Literal* it, Literal* end);
	Literal* small();
	LitRange tail();
};

//! Constraint for Loop-Formulas.
/*!
 * \ingroup constraint
 * Special purpose constraint for loop formulas of the form: L v B1 v ... v Bm,
 * where L is an unfounded set represented as a set of atom literals {~a1, ..., ~an}.
 * Representing such a loop formula explicitly as n clauses
 *   - (1) ~a1 v B1 v ... v Bm
 *   - ...
 *   - (n) ~an v B1 v ... v Bm
 *   .
 * is wasteful because each clause contains the same set of bodies.
 *
 * The idea behind LoopFormula is to treat L as a "macro-literal"
 * with the following properties:
 * - isTrue(L), iff for all ai isTrue(~ai)
 * - isFalse(L), iff for some ai isFalse(~ai)
 * - L is watchable, iff not isFalse(L)
 * - Watching L means watching all ai.
 * - setting L to true means setting all ai to false.
 * Using this convention the TWL-algo can be implemented as in a clause.
 *
 * \par Implementation:
 * - The literal-array is divided into two parts, an "active clause" part and an atom part.
 * - The "active clause" contains one atom and all bodies: [~ai B1 ... Bj]
 * - The atom part contains all atoms: [~a1 ... ~an]
 * - Two of the literals of the "active clause" are watched (again: watching an atom means watching all atoms)
 * - If a watched atom becomes true, it is copied into the "active clause" and the TWL-algo starts.
 */
class LoopFormula : public Constraint {
public:
	//! Creates a new loop-constraint for the given atoms.
	/*!
	* \param s      Solver in which the new constraint is to be used.
	* \param c1     First clause of the new constraint.
	* \param atoms  Set of atoms in the loop.
	* \param nAtoms Number of atoms in the loop.
	* \param updateHeuristic Whether to notify heuristic about new constraint.
	*
	* \pre The clause given in c1 is prepared and c1.size > 1 and c1.lits[0] is a literal in atoms.
	* \see ClauseCreator::prepare()
	*/
	static LoopFormula* newLoopFormula(Solver& s, const ClauseRep& c1, const Literal* atoms, uint32 nAtoms, bool updateHeuristic = true);

	//! Returns the number of literals in the loop-formula.
	uint32 size() const;

	// Constraint interface
	Constraint* cloneAttach(Solver&) { return 0; }
	PropResult  propagate(Solver& s, Literal p, uint32& data);
	void reason(Solver&, Literal p, LitVec& lits);
	bool minimize(Solver& s, Literal p, CCMinRecursive* ccMin);
	bool simplify(Solver& s, bool = false);
	void destroy(Solver* = 0, bool = false);

	// LearntConstraint interface
	bool locked(const Solver& s) const;

	uint32 isOpen(const Solver& s, const TypeSet& t, LitVec& freeLits);

	//! Returns the loop-formula's activity.
	/*!
	 * The activity of a loop-formula is increased, whenever reason() is called.
	 */
	ScoreType activity() const { return act_; }

	//! Halves the loop-formula's activity.
	void decreaseActivity() { act_.reduce(); }
	void resetActivity()    { act_.reset(); }

	//! Returns Constraint_t::Loop.
	ConstraintType type() const { return Constraint_t::Loop; }
private:
	LoopFormula(Solver& s, const ClauseRep& c1, const Literal* atoms, uint32 nAtoms, bool heu);
	void detach(Solver& s);
	bool otherIsSat(const Solver& s);
	Literal* begin() { return lits_ + 1; }
	Literal* xBegin(){ return lits_ + end_ + 1; }
	Literal* xEnd()  { return lits_ + size_; }
	ScoreType act_;     // activity of constraint
	uint32    end_;     // position of second sentinel
	uint32    size_:30; // size of lits_
	uint32    str_ : 1; // removed literal(s) during simplify?
	uint32    xPos_: 1; // position of ai in lits_ or 0 if no atom
	uint32    other_;   // stores the position of a literal that was recently true
POTASSCO_WARNING_BEGIN_RELAXED
	Literal   lits_[0]; // S ai B1...Bm S a1...an
POTASSCO_WARNING_END_RELAXED
};

namespace mt {

//! Stores the local part of a shared clause.
/*!
 * \ingroup constraint
 * The local part of a shared clause consists of a
 * clause head and and a pointer to the shared literals.
 * Since the local part is owned by a particular solver
 * it can be safely modified. Destroying a SharedLitsClause
 * means destroying the local part and decreasing the
 * shared literals' reference count.
 */
class SharedLitsClause : public ClauseHead {
public:
	//! Creates a new SharedLitsClause to be used in the given solver.
	/*!
	 * \param s The solver in which this clause will be used.
	 * \param shared_lits The shared literals of this clause.
	 * \param e Initial meta data for the new (local) clause.
	 * \param lits Watches and cache literal for the new (local) clause.
	 * \param addRef Increment ref count of shared_lits.
	 */
	static ClauseHead* newClause(Solver& s, SharedLiterals* shared_lits, const InfoType& e, const Literal* lits, bool addRef = true);

	Constraint* cloneAttach(Solver& other);
	void        reason(Solver& s, Literal p, LitVec& out);
	bool        minimize(Solver& s, Literal p, CCMinRecursive* rec);
	bool        isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN);
	bool        simplify(Solver& s, bool);
	void        destroy(Solver* s, bool detach);
	uint32      isOpen(const Solver& s, const TypeSet& t, LitVec& freeLits);
	uint32      size() const;
	void        toLits(LitVec& out) const;
private:
	SharedLitsClause(Solver& s, SharedLiterals* x, const Literal* lits, const InfoType&, bool addRef);
	bool     updateWatch(Solver& s, uint32 pos);
	BoolPair strengthen(Solver& s, Literal p, bool allowToShort);
};
}

}
#endif
clingo-5.2.2/clasp/clasp/cli/000077500000000000000000000000001320011352300157345ustar00rootroot00000000000000clingo-5.2.2/clasp/clasp/cli/clasp_cli_configs.inl000066400000000000000000000146041320011352300221060ustar00rootroot00000000000000//
// Copyright (c) 2013-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
/*!
 * \file
 * \brief Supermacros for defining clasp's default configurations.
 * \code
 * CONFIG(sId, name, "", "", "")
 * \endcode
 *
 * A configuration consists of a solver id and a name followed by three option strings:
 * - ""     : options that are always part of the configuration
 * - "": options to add if configuration is used as a stand-alone configuration (e.g. global options)
 * - ""  : options to add if configuration is used in a portfolio
 * .
 * \note The solver id is used to identify a configuration in the default portfolio.
 */

#if !defined(CONFIG) || (!defined(CLASP_CLI_DEFAULT_CONFIGS) && !defined(CLASP_CLI_AUX_CONFIGS))
#error Invalid include context
#endif

//! Named default configurations accessible via option "--configuration=".
#if defined(CLASP_CLI_DEFAULT_CONFIGS)
CLASP_CLI_DEFAULT_CONFIGS
CONFIG(0, tweety\
       , "--heuristic=Vsids,92 --restarts=L,60 --deletion=basic,50 --del-max=2000000 --del-estimate=1 --del-cfl=+,2000,100,20 --del-grow=0 --del-glue=2,0"\
         " --strengthen=recursive,all --otfs=2 --init-moms --score-other=all --update-lbd=less --save-progress=160 --init-watches=least --local-restarts --loops=shared"\
       , "--eq=3 --trans-ext=dynamic"\
       , "--opt-strat=bb,hier")
CONFIG(1, trendy\
       , "--heuristic=Vsids --restarts=D,100,0.7 --deletion=basic,50 --del-init=3.0,500,19500 --del-grow=1.1,20.0,x,100,1.5 --del-cfl=+,10000,2000 --del-glue=2"\
         " --strengthen=recursive --update-lbd=less --otfs=2 --save-p=75 --counter-restarts=3,1023 --reverse-arcs=2 --contraction=250 --loops=common"\
       , "--sat-p=2,iter=20,occ=25,time=240 --trans-ext=dynamic"\
       , "--opt-heu=sign --opt-strat=usc,disjoint")
CONFIG(2, frumpy\
       , "--heuristic=Berkmin --restarts=x,100,1.5 --deletion=basic,75 --del-init=3.0,200,40000 --del-max=400000 --contraction=250 --loops=common --save-p=180"\
         " --del-grow=1.1 --strengthen=local --sign-def-disj=pos"\
       , "--eq=5"\
       , "--restart-on-model --opt-heu=model")
CONFIG(3, crafty\
       , "--restarts=x,128,1.5 --deletion=basic,75 --del-init=10.0,1000,9000 --del-grow=1.1,20.0 --del-cfl=+,10000,1000 --del-glue=2 --otfs=2"\
         " --reverse-arcs=1 --counter-restarts=3,9973 --contraction=250"\
       , "--sat-p=2,iter=10,occ=25,time=240 --trans-ext=dynamic --backprop --heuristic=Vsids --save-p=180"\
       , "--heuristic=domain --dom-mod=neg,opt --opt-strat=bb,hier")
CONFIG(4, jumpy\
       , "--heuristic=Vsids --restarts=L,100 --deletion=basic,75,mixed --del-init=3.0,1000,20000 --del-grow=1.1,25,x,100,1.5 --del-cfl=x,10000,1.1 --del-glue=2"\
         " --update-lbd=glucose --strengthen=recursive --otfs=2 --save-p=70"\
       , "--sat-p=2,iter=20,occ=25,time=240 --trans-ext=dynamic"\
       , "--restart-on-model --opt-heu=sign,model --opt-strat=bb,inc")
CONFIG(5, handy\
       , "--heuristic=Vsids --restarts=D,100,0.7 --deletion=sort,50,mixed --del-max=200000 --del-init=20.0,1000,14000 --del-cfl=+,4000,600 --del-glue=2 --update-lbd=less"\
         " --strengthen=recursive --otfs=2 --save-p=20 --contraction=600 --loops=distinct --counter-restarts=7,1023 --reverse-arcs=2"\
       , "--sat-p=2,iter=10,occ=25,time=240 --trans-ext=dynamic --backprop"\
       , "")
#undef CLASP_CLI_DEFAULT_CONFIGS
#endif
//! Auxiliary configurations accessible via default portfolio ("--configuration=many").
#if defined(CLASP_CLI_AUX_CONFIGS)
CLASP_CLI_AUX_CONFIGS
CONFIG(6,  s6,  "--heuristic=Berkmin,512 --restarts=x,100,1.5 --deletion=basic,75 --del-init=3.0,200,40000 --del-max=400000 --contraction=250 --loops=common --del-grow=1.1,25 --otfs=2 --reverse-arcs=2 --strengthen=recursive --init-w=least --lookahead=atom,10", "", "")
CONFIG(7,  s7,  "--heuristic=Vsids --reverse-arcs=1 --otfs=1 --local-restarts --save-progress=0 --contraction=250 --counter-restart=7,200 --restarts=x,100,1.5 --del-init=3.0,800,-1 --deletion=basic,60 --strengthen=local --del-grow=1.0,1.0 --del-glue=4 --del-cfl=+,4000,300,100",  "", "")
CONFIG(8,  s8,  "--heuristic=Vsids --restarts=L,256 --counter-restart=3,9973 --strengthen=recursive --update-lbd=less --del-glue=2 --otfs=2 --deletion=ipSort,75,mixed --del-init=20.0,1000,19000", "", "")
CONFIG(9,  s9,  "--heuristic=Berkmin,512 --restarts=F,16000 --lookahead=atom,50",  "", "")
CONFIG(10, s10, "--heuristic=Vmtf --strengthen=no --contr=0 --restarts=x,100,1.3 --del-init=3.0,800,9200",  "", "")
CONFIG(11, s11, "--heuristic=Vsids --strengthen=recursive --restarts=x,100,1.5,15 --contraction=0",  "", "")
CONFIG(12, s12, "--heuristic=Vsids --restarts=L,128 --save-p --otfs=1 --init-w=least --contr=0 --opt-heu=sign,model",  "", "")
CONFIG(13, s13, "--heuristic=Berkmin,512 --restarts=x,100,1.5,6 --local-restarts --init-w=least --contr=0",  "", "")
CONFIG(14, nolearn, "--no-lookback --heuristic=Unit --lookahead=atom --deletion=no --restarts=no",  "", "")
CONFIG(15, tester,  "--heuristic=Vsids --restarts=D,100,0.7 --deletion=sort,50,mixed --del-max=200000 --del-init=20.0,1000,14000 --del-cfl=+,4000,600 --del-glue=2 --update-lbd=less"\
                    " --strengthen=recursive --otfs=2 --save-p=20 --contraction=600 --counter-restarts=7,1023 --reverse-arcs=2"\
                 ,  "--sat-p=2,iter=10,occ=25,time=240", "")
#undef CLASP_CLI_AUX_CONFIGS
#endif
#undef CONFIG
clingo-5.2.2/clasp/clasp/cli/clasp_cli_options.inl000066400000000000000000001332271320011352300221540ustar00rootroot00000000000000//
// Copyright (c) 2013-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
/*!
 * \file
 * \brief Supermacros for describing clasp's options.
 * \code
 * OPTION(key, "ext", ARG(...), "help", set, get)
 * \endcode
 * An option consists of:
 *  - a key  (valid and unique c identifier in 'snake_case')
 *  - a key extension ("[!][,][,@]") as understood by ProgramOptions::OptionInitHelper
 *  - an arg description (ARG macro) as understood by ProgramOptions::Value
 *  - a description (string)
 *  - a set action to be executed when a value (string) for the option is found in a source
 *  - a get action to be executed when the current value for an option is requested
 *  .
 *
 * \note In the implementation of ClaspCliConfig, each key is mapped to an enumeration constant and
 * the stringified version of key (i.e. \#key) is used to identify options.
 * Furthermore, the key is also used for generating command-line option names.
 * As a convention, compound keys using 'snake_case' to separate words
 * are mapped to dash-separated command-line option names.
 * E.g. an \ is mapped to the command-line option "option-like-this".
 *
 * \note ClaspCliConfig assumes a certain option order. In particular, context options shall
 * precede all solver/search options, which in turn shall precede global asp/solving options.
 *
 * \note The following set actions may be used:
 *  - STORE(obj): converts the string value to the type of obj and stores the result in obj.
 *  - STORE_U(E, n): converts the string value to type E and stores it as unsigned int in n.
 *  - STORE_LEQ(n, max): converts the string value to an unsinged int and stores the result in n if it is <= max.
 *  - STORE_FLAG(n): converts the string value to a bool and stores the result in n as either 0 or 1.
 *  - STORE_OR_FILL(n): converts the string value to an unsinged int t and sets n to std::min(t, maxValue(n)).
 *  - FUN(arg): anonymous function of type bool (ArgStream& arg), where arg provides the following interface:
 *    - arg.ok()     : returns whether arg is still valid
 *    - arg.empty()  : returns whether arg is empty (i.e. all tokens were extracted)
 *    - arg.off()    : returns whether arg contains a single token representing a valid off value
 *    - arg >> x     : extracts and converts the current token and stores it in x. Sets failbit if conversion fails.
 *    - arg >> opt(x): extracts an optional argument, shorthand for (!arg.empty() ? arg>>obj : arg)
 *    .
 *
 * \note The following get actions may be used:
 *  - GET_FUN(str)  : anonymous function of type void (OutputStream& str)
 *  - GET(obj...)   : shorthand for GET_FUN(str) { (str << obj)...; }
 *  - GET_IF(C, obj): shorthand for GET_FUN(str) { ITE(C, str << obj, str << off); }
 *  .
 *
 * \note The following primitives may be used in the set/get arguments:
 *  - off                  : singleton object representing a valid off value ("no", "off", "false", "0")
 *  - ITE(C, x, y)         : if-then-else expression, i.e. behaves like (C ? x : y).
 *  - SET(x, y)            : shorthand for (x=y) == y.
 *  - SET_LEQ(x, v, m)     : shorthand for (x <= m && SET(x, v)).
 *  - SET_GEQ(x, v, m)     : shorthand for (x >= m && SET(x, v)).
 *  - SET_OR_FILL(x, v)    : behaves like SET(x, min(v, maxValue(x)))
 *  - SET_OR_ZERO(x,v)     : behaves like ITE(v <= maxValue(x), SET(x, v), SET(x, 0)).
 *  .
 */
#if !defined(OPTION) || defined(SELF) || !defined(CLASP_HAS_THREADS)
#error Invalid include context
#endif

#if !defined(GROUP_BEGIN)
#define GROUP_BEGIN(X)
#endif

#if !defined(GROUP_END)
#define GROUP_END(X)
#endif

//! Options for configuring a SharedContext object stored in a Clasp::ContextParams object.
#if defined(CLASP_CONTEXT_OPTIONS)
#define SELF CLASP_CONTEXT_OPTIONS
GROUP_BEGIN(SELF)
OPTION(share, "!,@1", ARG_EXT(defaultsTo("auto")->state(Value::value_defaulted), DEFINE_ENUM_MAPPING(ContextParams::ShareMode, \
       MAP("no"  , ContextParams::share_no)  , MAP("all", ContextParams::share_all),\
       MAP("auto", ContextParams::share_auto), MAP("problem", ContextParams::share_problem),\
       MAP("learnt", ContextParams::share_learnt))),\
       "Configure physical sharing of constraints [%D]\n"\
       "      %A: {auto|problem|learnt|all}", FUN(arg) {ContextParams::ShareMode x; return arg>>x && SET(SELF.shareMode, (uint32)x);}, GET((ContextParams::ShareMode)SELF.shareMode))
OPTION(learn_explicit, ",@2" , ARG(flag()), "Do not use Short Implication Graph for learning", STORE_FLAG(SELF.shortMode), GET(SELF.shortMode))
OPTION(sat_prepro    , "!,@1", ARG(arg("")->implicit("2")),                     \
       "Run SatELite-like preprocessing (Implicit: %I)\n"                            \
       "      %A: [,...]\n"                                            \
       "         : Set preprocessing level to \n"              \
       "          1: Variable elimination with subsumption (VE)\n"                   \
       "          2: VE with limited blocked clause elimination (BCE)\n"             \
       "          3: Full BCE followed by VE\n"                                      \
       "         : [=] (0=no limit)\n"  \
       "          iter  : Set iteration limit to            [0]\n"                \
       "          occ   : Set variable occurrence limit to  [0]\n"                \
       "          time  : Set time limit to  seconds        [0]\n"                \
       "          frozen: Set frozen variables limit to %%   [0]\n"               \
       "          size  : Set size limit to *1000 clauses   [4000]", STORE(SELF.satPre), GET(SELF.satPre))
GROUP_END(SELF)
#undef CLASP_CONTEXT_OPTIONS
#undef SELF
#endif

//! Global options only valid in facade.
#if defined(CLASP_GLOBAL_OPTIONS)
#define SELF CLASP_GLOBAL_OPTIONS
GROUP_BEGIN(SELF)
OPTION(stats, ",s", ARG(implicit("1")->arg("[,]")), "Enable {1=basic|2=full} statistics ( for tester)",\
    FUN(arg) { uint32 s = 0; uint32 t = 0;\
      return (arg.off() || (arg >> s >> opt(t) && s > 0))
        && SET(SELF.stats, s) && ((!SELF.testerConfig() && t == 0) || SET(SELF.addTesterConfig()->stats, t));
    },\
    GET_FUN(str) { ITE(!SELF.testerConfig() || !SELF.testerConfig()->stats, str << SELF.stats, str << SELF.stats << SELF.testerConfig()->stats); })
OPTION(parse_ext, "!", ARG(flag()), "Enable extensions in non-aspif input",\
    FUN(arg) { bool b = false; return (arg.off() || arg >> b) && (SELF.parse.assign(ParserOptions::parse_full, b), true); }, \
    GET((SELF.parse.anyOf(ParserOptions::parse_full))))
OPTION(parse_maxsat, "!", ARG(flag()), "Treat dimacs input as MaxSAT problem", \
    FUN(arg) { bool b = false; return (arg.off() || arg >> b) && (SELF.parse.assign(ParserOptions::parse_maxsat, b), true); }, \
    GET(static_cast(SELF.parse.isEnabled(ParserOptions::parse_maxsat))))
GROUP_END(SELF)
#undef CLASP_GLOBAL_OPTIONS
#undef SELF
#endif

//! Solver options (see SolverParams).
#if defined(CLASP_SOLVER_OPTIONS)
#define SELF CLASP_SOLVER_OPTIONS
GROUP_BEGIN(SELF)
OPTION(opt_strategy , ""  , ARG_EXT(arg(""),\
       DEFINE_ENUM_MAPPING(OptParams::Type, MAP("bb", OptParams::type_bb), MAP("usc", OptParams::type_usc))\
       DEFINE_ENUM_MAPPING(OptParams::BBAlgo, MAP("lin", OptParams::bb_lin), MAP("hier", OptParams::bb_hier), MAP("inc", OptParams::bb_inc), MAP("dec", OptParams::bb_dec))\
       DEFINE_ENUM_MAPPING(OptParams::UscAlgo, MAP("oll", OptParams::usc_oll), MAP("one", OptParams::usc_one), MAP("k", OptParams::usc_k), MAP("pmres", OptParams::usc_pmr))\
       DEFINE_ENUM_MAPPING(OptParams::UscOption, MAP("disjoint", OptParams::usc_disjoint), MAP("succinct", OptParams::usc_succinct), MAP("stratify", OptParams::usc_stratify))),\
       "Configure optimization strategy\n" \
       "      %A: {bb|usc}[,]\n" \
       "        bb : Model-guided optimization with  [lin]\n" \
       "          lin : Basic lexicographical descent\n"                                  \
       "          hier: Hierarchical (highest priority criteria first) descent \n"        \
       "          inc : Hierarchical descent with exponentially increasing steps\n"       \
       "          dec : Hierarchical descent with exponentially decreasing steps\n"       \
       "        usc: Core-guided optimization with : [,]\n"         \
       "          : Relaxation algorithm {oll|one|k|pmres}                [oll]\n" \
       "            oll    : Use strategy from unclasp\n"                                 \
       "            one    : Add one cardinality constraint per core\n"                   \
       "            k[,]: Add cardinality constraints of bounded size ([0]=dynamic)\n" \
       "            pmres  : Add clauses of size 3\n"                                     \
       "           : Tactics |\n"   \
       "            disjoint: Disjoint-core preprocessing                    (1)\n"       \
       "            succinct: No redundant (symmetry) constraints            (2)\n"       \
       "            stratify: Stratification heuristic for handling weights  (4)",        \
       STORE(SELF.opt), GET(SELF.opt))
OPTION(opt_usc_shrink, "", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(OptParams::UscTrim, \
       MAP("lin", OptParams::usc_trim_lin), MAP("rgs", OptParams::usc_trim_rgs), MAP("min", OptParams::usc_trim_min),\
       MAP("exp", OptParams::usc_trim_exp), MAP("inv", OptParams::usc_trim_inv), MAP("bin", OptParams::usc_trim_bin))),\
       "Enable core-shrinking in core-guided optimization\n"        \
       "      %A: [, (0=no limit)]\n"                  \
       "         : Use algorithm {lin|inv|bin|rgs|exp|min}\n" \
       "          lin  : Forward linear search unsat\n"             \
       "          inv  : Inverse linear search not unsat\n"         \
       "          bin  : Binary search\n"                           \
       "          rgs  : Repeated geometric sequence until unsat\n" \
       "          exp  : Exponential search until unsat\n"          \
       "          min  : Linear search for subset minimal core\n"   \
       "        : Limit solve calls to 2^ conflicts [10]",\
      FUN(arg) {\
        OptParams::UscTrim t = (OptParams::UscTrim)0; uint32 n = 0; \
        return (arg.off() || arg >> t >> opt(n=10)) && SET(SELF.opt.trim, uint32(t)) && SET(SELF.opt.tLim, uint32(n)); },\
      GET_IF(SELF.opt.trim, (OptParams::UscTrim)SELF.opt.trim, SELF.opt.tLim))
OPTION(opt_heuristic, "", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(OptParams::Heuristic, \
       MAP("sign", OptParams::heu_sign), MAP("model", OptParams::heu_model))),\
       "Use opt. in  heuristics",\
       FUN(arg) { Set h; return (arg.off() || arg >> h) && SET(SELF.opt.heus, h.value());},\
       GET(Set(SELF.opt.heus)))
OPTION(restart_on_model, "!", ARG(flag()), "Restart after each model\n", STORE_FLAG(SELF.restartOnModel), GET(SELF.restartOnModel))
OPTION(lookahead    , "!", ARG_EXT(implicit("atom"), DEFINE_ENUM_MAPPING(VarType, \
       MAP("atom", Var_t::Atom), MAP("body", Var_t::Body), MAP("hybrid", Var_t::Hybrid))),\
       "Configure failed-literal detection (fld)\n" \
       "      %A: [,] / Implicit: %I\n" \
       "         : Run fld via {atom|body|hybrid} lookahead\n" \
       "        : Disable fld after  applications ([0]=no limit)\n" \
       "      --lookahead=atom is default if --no-lookback is used\n", FUN(arg) { \
       VarType type = Var_t::Atom; uint32 limit = (SELF.lookOps = 0u);\
       return ITE(arg.off(), SET(SELF.lookType, 0u), arg>>type>>opt(limit) && SET(SELF.lookType, (uint32)type)) && SET_OR_ZERO(SELF.lookOps, limit);},\
       GET_IF(SELF.lookType, (VarType)SELF.lookType, SELF.lookOps))
OPTION(heuristic, "", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(Heuristic_t::Type, \
       MAP("berkmin", Heuristic_t::Berkmin), MAP("vmtf"  , Heuristic_t::Vmtf), \
       MAP("vsids"  , Heuristic_t::Vsids)  , MAP("domain", Heuristic_t::Domain), \
       MAP("unit"   , Heuristic_t::Unit)   , MAP("auto", Heuristic_t::Default), MAP("none"  , Heuristic_t::None))), \
       "Configure decision heuristic\n"  \
       "      %A: {Berkmin|Vmtf|Vsids|Domain|Unit|None}[,]\n" \
       "        Berkmin: Use BerkMin-like heuristic (Check last  nogoods [0]=all)\n" \
       "        Vmtf   : Use Siege-like heuristic (Move  literals to the front [8])\n" \
       "        Vsids  : Use Chaff-like heuristic (Use 1.0/0. as decay factor  [95])\n"\
       "        Domain : Use domain knowledge in Vsids-like heuristic\n"\
       "        Unit   : Use Smodels-like heuristic (Default if --no-lookback)\n" \
       "        None   : Select the first free variable", FUN(arg) { Heuristic_t::Type h = Heuristic_t::Berkmin; uint32 n = 0u; \
       return arg>>h>>opt(n) && SET(SELF.heuId, (uint32)h) && (Heuristic_t::isLookback(h) || !n) && SET_OR_FILL(SELF.heuristic.param, n);},\
       GET((Heuristic_t::Type)SELF.heuId, SELF.heuristic.param))
OPTION(init_moms  , "!,@2", ARG(flag())    , "Initialize heuristic with MOMS-score", STORE_FLAG(SELF.heuristic.moms), GET(SELF.heuristic.moms))
OPTION(score_res  , ",@2" , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(HeuParams::Score, \
       MAP("auto", HeuParams::score_auto), MAP("min", HeuParams::score_min), MAP("set", HeuParams::score_set), MAP("multiset", HeuParams::score_multi_set))),\
       "Resolution score {auto|min|set|multiset}", STORE_U(HeuParams::Score, SELF.heuristic.score), GET(static_cast(SELF.heuristic.score)))
OPTION(score_other, ",@2" , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(HeuParams::ScoreOther, \
       MAP("auto", HeuParams::other_auto), MAP("no", HeuParams::other_no), MAP("loop", HeuParams::other_loop), MAP("all", HeuParams::other_all))),\
       "Score other learnt nogoods: {auto|no|loop|all}", STORE_U(HeuParams::ScoreOther, SELF.heuristic.other), GET(static_cast(SELF.heuristic.other)))
OPTION(sign_def   , ",@1" , ARG_EXT(arg(""),\
       DEFINE_ENUM_MAPPING(SolverStrategies::SignHeu, MAP("asp", SolverStrategies::sign_atom), MAP("pos", SolverStrategies::sign_pos), MAP("neg", SolverStrategies::sign_neg), MAP("rnd", SolverStrategies::sign_rnd))),\
       "Default sign: {asp|pos|neg|rnd}", STORE_U(SolverStrategies::SignHeu, SELF.signDef), GET((SolverStrategies::SignHeu)SELF.signDef))
OPTION(sign_fix   , "!,@2", ARG(flag())    , "Disable sign heuristics and use default signs only", STORE_FLAG(SELF.signFix), GET(SELF.signFix))
OPTION(berk_huang , "!,@2", ARG(flag())    , "Enable Huang-scoring in Berkmin", STORE_FLAG(SELF.heuristic.huang), GET(SELF.heuristic.huang))
OPTION(vsids_acids, "!,@2", ARG(flag())    , "Enable acids-scheme in Vsids/Domain", STORE_FLAG(SELF.heuristic.acids), GET(SELF.heuristic.acids))
OPTION(vsids_progress, ",@2", NO_ARG, "Enable dynamic decaying scheme in Vsids/Domain\n"\
       "      %A: [,][,]|(0=disable)\n"\
       "         : Set initial decay factor to 1.0/0.\n"\
       "         : Set decay update to /100.0      [1]\n"\
       "         : Decrease decay every  conflicts [5000]", \
       FUN(arg) { uint32 n = 80; uint32 i = 1; uint32 c = 5000; \
       return ITE(arg.off(), SET(SELF.heuristic.decay.init, 0), (arg >> n >> opt(i) >> opt(c))\
         && SET(SELF.heuristic.decay.init, n) && SET_LEQ(SELF.heuristic.decay.bump, i, 100) && SET(SELF.heuristic.decay.freq, c));}, \
       GET_IF(SELF.heuristic.decay.init, SELF.heuristic.decay.init, SELF.heuristic.decay.bump, SELF.heuristic.decay.freq))
OPTION(nant       , "!,@2", ARG(flag())    , "Prefer negative antecedents of P in heuristic", STORE_FLAG(SELF.heuristic.nant), GET(SELF.heuristic.nant))
OPTION(dom_mod    , ",@1" , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(HeuParams::DomMod, \
       MAP("level", HeuParams::mod_level), MAP("pos", HeuParams::mod_spos), MAP("true", HeuParams::mod_true),\
       MAP("neg", HeuParams::mod_sneg), MAP("false", HeuParams::mod_false), MAP("init", HeuParams::mod_init), MAP("factor", HeuParams::mod_factor))\
       DEFINE_ENUM_MAPPING(HeuParams::DomPref, MAP("all", HeuParams::pref_atom), MAP("scc", HeuParams::pref_scc), MAP("hcc", HeuParams::pref_hcc),\
       MAP("disj", HeuParams::pref_disj), MAP("opt", HeuParams::pref_min), MAP("show", HeuParams::pref_show))),\
       "Default modification for domain heuristic\n"\
       "      %A: (no|[,])\n"\
       "          : Modifier {level|pos|true|neg|false|init|factor}\n"\
       "         : Apply  to (all | ) atoms", \
       FUN(arg) { HeuParams::DomMod modK; unsigned modN = 0; Set k; bool ok = true;\
         if (!arg.off()) { ok = ITE(arg.peek() >= 'A', arg >> modK && SET(modN, uint32(modK)), arg >> modN && modN > 0u && modN < 8u); }\
         return ok && (arg.off() || arg >> opt(k)) && SET(SELF.heuristic.domMod, modN) && SET(SELF.heuristic.domPref, k.value());},\
       GET_FUN(str) { Set mod(SELF.heuristic.domMod); Set pick(SELF.heuristic.domPref); \
         ITE(mod.value() && pick.value(), str << mod << pick, str << mod); })
OPTION(save_progress, "", ARG(implicit("1")->arg("")), "Use RSat-like progress saving on backjumps > %A", STORE_OR_FILL(SELF.saveProgress), GET(SELF.saveProgress))
OPTION(init_watches , ",@2", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolverStrategies::WatchInit, \
       MAP("rnd", SolverStrategies::watch_rand), MAP("first", SolverStrategies::watch_first), MAP("least", SolverStrategies::watch_least))),\
       "Watched literal initialization: {rnd|first|least}", STORE_U(SolverStrategies::WatchInit, SELF.initWatches), GET(static_cast(SELF.initWatches)))
OPTION(update_mode   , ",@2", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolverStrategies::UpdateMode, \
       MAP("propagate", SolverStrategies::update_on_propagate), MAP("conflict", SolverStrategies::update_on_conflict))),\
       "Process messages on {propagate|conflict}", STORE_U(SolverStrategies::UpdateMode, SELF.upMode), GET(static_cast(SELF.upMode)))
OPTION(acyc_prop, ",@2", ARG(implicit("1")->arg("{0..1}")), "Use backward inference in acyc propagation", \
       FUN(arg) { uint32 x; return arg>>x && SET_LEQ(SELF.acycFwd, (1u-x), 1u); }, GET(1u-SELF.acycFwd))
OPTION(seed          , ""   , ARG(arg("")),"Set random number generator's seed to %A", STORE(SELF.seed), GET(SELF.seed))
OPTION(no_lookback   , ""   , ARG(flag()), "Disable all lookback strategies\n", STORE_FLAG(SELF.search),GET(static_cast(SELF.search == SolverStrategies::no_learning)))
OPTION(forget_on_step, ""   , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolverParams::Forget, \
       MAP("varScores", SolverParams::forget_heuristic), MAP("signs", SolverParams::forget_signs), MAP("lemmaScores", SolverParams::forget_activities), MAP("lemmas", SolverParams::forget_learnts))),\
       "Configure forgetting on (incremental) step\n"\
       "      %A: |\n",\
       FUN(arg) { Set s; return (arg.off() || arg >> s) && SET(SELF.forgetSet, s.value()); },\
       GET(Set(SELF.forgetSet)))
OPTION(strengthen    , "!"  , ARG_EXT(arg(""),\
       DEFINE_ENUM_MAPPING(SolverStrategies::CCMinType, MAP("local", SolverStrategies::cc_local), MAP("recursive", SolverStrategies::cc_recursive))\
       DEFINE_ENUM_MAPPING(SolverStrategies::CCMinAntes, MAP("all", SolverStrategies::all_antes), MAP("short", SolverStrategies::short_antes), MAP("binary", SolverStrategies::binary_antes))), \
       "Use MiniSAT-like conflict nogood strengthening\n"                      \
       "      %A: [,][,]\n"                         \
       "        : Use {local|recursive} self-subsumption check\n"        \
       "        : Follow {all|short|binary} antecedents [all]\n"         \
       "        : Bump activities of antecedents        [yes]", FUN(arg) {\
       SolverStrategies::CCMinType m = SolverStrategies::cc_local; SolverStrategies::CCMinAntes t = SolverStrategies::no_antes; bool b = true; \
       return (arg.off() || arg>>m>>opt(t = SolverStrategies::all_antes)>>opt(b)) && SET(SELF.ccMinAntes, (uint32)t) && SET(SELF.ccMinRec, (uint32)m) && SET(SELF.ccMinKeepAct, uint32(!b)); }, \
       GET_IF(SELF.ccMinAntes != SolverStrategies::no_antes, (SolverStrategies::CCMinType)SELF.ccMinRec, (SolverStrategies::CCMinAntes)SELF.ccMinAntes, ITE(SELF.ccMinKeepAct, "no", "yes")))
OPTION(otfs        , ""   , ARG(implicit("1")->arg("{0..2}")), "Enable {1=partial|2=full} on-the-fly subsumption", STORE_LEQ(SELF.otfs, 2u), GET(SELF.otfs))
OPTION(update_lbd  , "!,@2" , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolverStrategies::LbdMode, \
       MAP("less", SolverStrategies::lbd_updated_less), MAP("glucose", SolverStrategies::lbd_update_glucose), MAP("pseudo", SolverStrategies::lbd_update_pseudo))),\
       "Configure LBD updates during conflict resolution\n"                 \
       "      %A: [,]\n"            \
       "        less   : update to X = new LBD   iff X   < previous LBD\n"  \
       "        glucose: update to X = new LBD   iff X+1 < previous LBD\n"  \
       "        pseudo : update to X = new LBD+1 iff X   < previous LBD\n"  \
       "            : Protect updated nogoods on next reduce if X <= ",\
       FUN(arg) { SolverStrategies::LbdMode n = SolverStrategies::lbd_fixed; uint32 m = 0; \
         return (arg.off() || (arg >> n >> opt(m) && n > 0)) && SET(SELF.updateLbd, uint32(n)) && SET_LEQ(search->reduce.strategy.protect, m, uint32(Clasp::LBD_MAX));},\
       GET_IF(SELF.updateLbd, (SolverStrategies::LbdMode)SELF.updateLbd, search->reduce.strategy.protect))
OPTION(update_act  , ",@2", ARG(flag()), "Enable LBD-based activity bumping", STORE_FLAG(SELF.bumpVarAct), GET(SELF.bumpVarAct))
OPTION(reverse_arcs, ""   , ARG(implicit("1")->arg("{0..3}")), "Enable ManySAT-like inverse-arc learning", STORE_LEQ(SELF.reverseArcs, 3u), GET(SELF.reverseArcs))
OPTION(contraction , "!,@2", ARG_EXT(arg(""),\
       DEFINE_ENUM_MAPPING(SolverStrategies::CCRepMode, MAP("no", SolverStrategies::cc_no_replace), MAP("decisionSeq", SolverStrategies::cc_rep_decision), MAP("allUIP", SolverStrategies::cc_rep_uip), MAP("dynamic", SolverStrategies::cc_rep_dynamic))),\
       "Configure handling of long learnt nogoods\n"
       "      %A: [,]\n"\
       "          : Contract nogoods if size >  (0=disable)\n"\
       "        : Nogood replacement {no|decisionSeq|allUIP|dynamic} [no]\n", FUN(arg) { uint32 n = 0; SolverStrategies::CCRepMode r = SolverStrategies::cc_no_replace;\
       return (arg.off() || (arg>>n>>opt(r) && n != 0u)) && SET_OR_FILL(SELF.compress, n) && SET(SELF.ccRepMode, uint32(r));},\
       GET_IF(SELF.compress, SELF.compress, (SolverStrategies::CCRepMode)SELF.ccRepMode))
OPTION(loops, "" , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(DefaultUnfoundedCheck::ReasonStrategy,\
       MAP("common"  , DefaultUnfoundedCheck::common_reason)  , MAP("shared", DefaultUnfoundedCheck::shared_reason), \
       MAP("distinct", DefaultUnfoundedCheck::distinct_reason), MAP("no", DefaultUnfoundedCheck::only_reason))),\
       "Configure learning of loop nogoods\n" \
       "      %A: {common|distinct|shared|no}\n" \
       "        common  : Create loop nogoods for atoms in an unfounded set\n" \
       "        distinct: Create distinct loop nogood for each atom in an unfounded set\n" \
       "        shared  : Create loop formula for a whole unfounded set\n" \
       "        no      : Do not learn loop formulas\n", FUN(arg) {DefaultUnfoundedCheck::ReasonStrategy x; return arg>>x && SET(SELF.loopRep, (uint32)x);},\
       GET(static_cast(SELF.loopRep)))
GROUP_END(SELF)
#undef CLASP_SOLVER_OPTIONS
#undef SELF
#endif

//! Search-related options (see SolveParams).
#if defined(CLASP_SEARCH_OPTIONS)
#define SELF CLASP_SEARCH_OPTIONS
GROUP_BEGIN(SELF)
OPTION(partial_check, "", ARG(implicit("50")), "Configure partial stability tests\n" \
       "      %A: 

[,] / Implicit: %I\n" \ "

: Partial check skip percentage\n" \ " : Init/update value for high bound ([0]=umax)", FUN(arg) {\ uint32 p = 0; uint32 h = 0; \ return (arg.off() || (arg>>p>>opt(h) && p)) && SET_LEQ(SELF.fwdCheck.highPct, p, 100u) && SET_OR_ZERO(SELF.fwdCheck.highStep, h);},\ GET_IF(SELF.fwdCheck.highPct, SELF.fwdCheck.highPct, SELF.fwdCheck.highStep)) OPTION(sign_def_disj, ",@2", ARG(arg("")), "Default sign for atoms in disjunctions", STORE_U(SolverStrategies::SignHeu, SELF.fwdCheck.signDef), GET((SolverStrategies::SignHeu)SELF.fwdCheck.signDef)) OPTION(rand_freq, "!", ARG(arg("

")), "Make random decisions with probability %A", FUN(arg) {\ double f = 0.0; \ return (arg.off() || arg>>f) && SET_R(SELF.randProb, (float)f, 0.0f, 1.0f);}, GET(SELF.randProb)) OPTION(rand_prob, "", ARG(arg("[,]")), "Do random searches with [=100] conflicts",\ FUN(arg) { uint32 n1 = 0; uint32 n2 = 100;\ return (arg.off() || (arg>>n1>>opt(n2) && n1)) && SET_OR_FILL(SELF.randRuns, n1) && SET_OR_FILL(SELF.randConf, n2);},\ GET_IF(SELF.randRuns, SELF.randRuns,SELF.randConf)) #undef SELF //! Options for configuring the restart strategy of a solver. #define SELF CLASP_SEARCH_RESTART_OPTIONS #if defined(NOTIFY_SUBGROUPS) GROUP_BEGIN(SELF) #endif OPTION(restarts, "!,r", ARG(arg("")), "Configure restart policy\n" \ " %A: ,[,][,]\n" \ " F, : Run fixed sequence of conflicts\n" \ " L, : Run Luby et al.'s sequence with unit length \n" \ " x,,: Run geometric seq. of *(^i) conflicts ( >= 1.0)\n" \ " +,,: Run arithmetic seq. of +(*i) conflicts ()\n"\ " ...,: Repeat seq. every +j restarts ( != F)\n" \ " D,,: Restart based on moving LBD average over last conflicts\n" \ " Mavg(,LBD)* > avg(LBD)\n" \ " use conflict level average if > 0 and avg(LBD) > \n"\ " no|0 : Disable restarts", FUN(arg) { return ITE(arg.off(), (SELF.disable(),true), \ arg>>SELF.sched && SET(SELF.dynRestart, uint32(SELF.sched.type == ScheduleStrategy::User)));}, GET(SELF.sched)) OPTION(reset_restarts , ",@2", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(RestartParams::SeqUpdate, \ MAP("no",RestartParams::seq_continue), MAP("repeat", RestartParams::seq_repeat), MAP("disable", RestartParams::seq_disable))),\ "Update restart seq. on model {no|repeat|disable}",\ STORE_U(RestartParams::SeqUpdate, SELF.upRestart), GET(static_cast(SELF.upRestart))) OPTION(local_restarts , "!" , ARG(flag()), "Use Ryvchin et al.'s local restarts", STORE_FLAG(SELF.cntLocal), GET(SELF.cntLocal)) OPTION(counter_restarts, "" , ARG(arg("")), "Use counter implication restarts\n" \ " %A: ([,] | {0|no})\n" \ " : Interval in number of restarts\n" \ " : Bump factor applied to indegrees", \ FUN(arg) { uint32 n = 0; uint32 m = SELF.counterBump; \ return (arg.off() || (arg >> n >> opt(m) && n > 0)) && SET_OR_FILL(SELF.counterRestart, n) && SET_OR_FILL(SELF.counterBump, m); },\ GET_IF(SELF.counterRestart, SELF.counterRestart, SELF.counterBump)) OPTION(block_restarts , "" , ARG(arg("")), "Use glucose-style blocking restarts\n" \ " %A: [,][,]\n" \ " : Window size for moving average (0=disable blocking)\n" \ " : Block restart if assignment > average * [1.4]\n" \ " : Disable blocking for the first conflicts [10000]\n", FUN(arg) { \ uint32 n = 0; double R = 0.0; uint32 x = 0;\ return (arg.off() || (arg>>n>>opt(R = 1.4)>>opt(x = 10000) && n && R >= 1.0 && R <= 5.0))\ && SET(SELF.blockWindow, n) && SET(SELF.blockScale, (float)R) && SET_OR_FILL(SELF.blockFirst, x);},\ GET_IF(SELF.blockWindow, SELF.blockWindow, SELF.blockScale, SELF.blockFirst)) OPTION(shuffle , "!" , ARG(arg(",")), "Shuffle problem after +(*i) restarts\n", FUN(arg) { uint32 n1 = 0; uint32 n2 = 0;\ return (arg.off() || (arg>>n1>>opt(n2) && n1)) && SET_OR_FILL(SELF.shuffle, n1) && SET_OR_FILL(SELF.shuffleNext, n2);},\ GET_IF(SELF.shuffle, SELF.shuffle, SELF.shuffleNext)) #if defined(NOTIFY_SUBGROUPS) GROUP_END(SELF) #endif #undef SELF #undef CLASP_SEARCH_RESTART_OPTIONS //! Options for configuring the deletion strategy of a solver. #define SELF CLASP_SEARCH_REDUCE_OPTIONS #if defined(NOTIFY_SUBGROUPS) GROUP_BEGIN(SELF) #endif OPTION(deletion , "!,d", ARG_EXT(defaultsTo("basic,75,0")->state(Value::value_defaulted), DEFINE_ENUM_MAPPING(ReduceStrategy::Algorithm,\ MAP("basic", ReduceStrategy::reduce_linear), MAP("sort", ReduceStrategy::reduce_stable),\ MAP("ipSort", ReduceStrategy::reduce_sort) , MAP("ipHeap", ReduceStrategy::reduce_heap))\ DEFINE_ENUM_MAPPING(ReduceStrategy::Score, MAP("activity",ReduceStrategy::score_act), MAP("lbd", ReduceStrategy::score_lbd), MAP("mixed", ReduceStrategy::score_both))),\ "Configure deletion algorithm [%D]\n" \ " %A: [,][,]\n" \ " : Use {basic|sort|ipSort|ipHeap} algorithm\n" \ " : Delete at most %% of nogoods on reduction [75]\n" \ " : Use {activity|lbd|mixed} nogood scores [activity]\n" \ " no : Disable nogood deletion", FUN(arg){\ ReduceStrategy::Algorithm algo = ReduceStrategy::reduce_linear; uint32 n; ReduceStrategy::Score sc;\ return ITE(arg.off(), (SELF.disable(), true), arg>>algo>>opt(n = 75)>>opt(sc = ReduceStrategy::score_act)\ && SET(SELF.strategy.algo, (uint32)algo) && SET_R(SELF.strategy.fReduce, n, 1, 100) && SET(SELF.strategy.score, (uint32)sc));},\ GET_IF(SELF.strategy.fReduce, (ReduceStrategy::Algorithm)SELF.strategy.algo, SELF.strategy.fReduce,(ReduceStrategy::Score)SELF.strategy.score)) OPTION(del_grow , "!", NO_ARG, "Configure size-based deletion policy\n" \ " %A: [,][,] ( >= 1.0)\n" \ " : Keep at most T = X*(^i) learnt nogoods with X being the\n"\ " initial limit and i the number of times fired\n" \ " : Stop growth once T > P* (0=no limit) [3.0]\n" \ " : Set grow schedule () [grow on restart]", FUN(arg){ double f; double g; ScheduleStrategy sc = ScheduleStrategy::def();\ return ITE(arg.off(), (SELF.growSched = ScheduleStrategy::none(), SELF.fGrow = 0.0f, true),\ arg>>f>>opt(g = 3.0)>>opt(sc) && SET_R(SELF.fGrow, (float)f, 1.0f, FLT_MAX) && SET_R(SELF.fMax, (float)g, 0.0f, FLT_MAX)\ && (sc.defaulted() || sc.type != ScheduleStrategy::User) && (SELF.growSched=sc, true));},\ GET_FUN(str) { if (SELF.fGrow == 0.0f) str<")), "Configure conflict-based deletion policy\n" \ " %A: ,... (see restarts)", FUN(arg){\ return ITE(arg.off(), (SELF.cflSched=ScheduleStrategy::none()).disabled(), arg>>SELF.cflSched && SELF.cflSched.type != ScheduleStrategy::User);}, GET(SELF.cflSched)) OPTION(del_init , "" , ARG(defaultsTo("3.0")->state(Value::value_defaulted)), "Configure initial deletion limit\n"\ " %A: [,,] ( > 0)\n" \ " : Set initial limit to P=estimated problem size/ [%D]\n" \ " ,: Clamp initial limit to the range [,+]" , FUN(arg) { double f; uint32 lo = 10; uint32 hi = UINT32_MAX;\ return arg>>f>>opt(lo)>>opt(hi) && f > 0.0 && (SELF.fInit = float(1.0 / f)) > 0 && SET_OR_FILL(SELF.initRange.lo, lo) && SET_OR_FILL(SELF.initRange.hi, (uint64(hi)+SELF.initRange.lo));},\ GET_IF(SELF.fInit, 1.0/SELF.fInit, SELF.initRange.lo, SELF.initRange.hi - SELF.initRange.lo)) OPTION(del_estimate, "", ARG(arg("0..3")->implicit("1")), "Use estimated problem complexity in limits", STORE_LEQ(SELF.strategy.estimate, 3u), GET(SELF.strategy.estimate)) OPTION(del_max , "!", ARG(arg(",")), "Keep at most learnt nogoods taking up to MB", FUN(arg) { uint32 n = UINT32_MAX; uint32 mb = 0; \ return (arg.off() || arg>>n>>opt(mb)) && SET_GEQ(SELF.maxRange, n, 1u) && SET(SELF.memMax, mb);}, GET(SELF.maxRange, SELF.memMax)) OPTION(del_glue , "", NO_ARG, "Configure glue clause handling\n" \ " %A: [,]\n" \ " : Do not delete nogoods with LBD <= \n" \ " : Count (0) or ignore (1) glue clauses in size limit [0]", FUN(arg) {uint32 lbd; uint32 m = 0; \ return arg>>lbd>>opt(m) && SET(SELF.strategy.glue, lbd) && SET(SELF.strategy.noGlue, m);}, GET(SELF.strategy.glue, SELF.strategy.noGlue)) OPTION(del_on_restart, "", ARG(arg("")), "Delete %A%% of learnt nogoods on each restart", STORE_LEQ(SELF.strategy.fRestart, 100u), GET(SELF.strategy.fRestart)) #if defined(NOTIFY_SUBGROUPS) GROUP_END(SELF) #endif #undef SELF #undef CLASP_SEARCH_REDUCE_OPTIONS GROUP_END(CLASP_SEARCH_OPTIONS) #undef CLASP_SEARCH_OPTIONS #endif //! ASP-front-end options stored in an Clasp::Asp::LogicProgram::AspOptions object. #if defined(CLASP_ASP_OPTIONS) #define SELF CLASP_ASP_OPTIONS GROUP_BEGIN(SELF) OPTION(trans_ext , "!", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(Asp::LogicProgram::ExtendedRuleMode,\ MAP("no" , Asp::LogicProgram::mode_native) , MAP("all" , Asp::LogicProgram::mode_transform),\ MAP("choice", Asp::LogicProgram::mode_transform_choice), MAP("card", Asp::LogicProgram::mode_transform_card),\ MAP("weight", Asp::LogicProgram::mode_transform_weight), MAP("scc" , Asp::LogicProgram::mode_transform_scc),\ MAP("integ" , Asp::LogicProgram::mode_transform_integ) , MAP("dynamic", Asp::LogicProgram::mode_transform_dynamic))),\ "Configure handling of extended rules\n"\ " %A: {all|choice|card|weight|integ|dynamic}\n"\ " all : Transform all extended rules to basic rules\n"\ " choice : Transform choice rules, but keep cardinality and weight rules\n"\ " card : Transform cardinality rules, but keep choice and weight rules\n"\ " weight : Transform cardinality and weight rules, but keep choice rules\n"\ " scc : Transform \"recursive\" cardinality and weight rules\n"\ " integ : Transform cardinality integrity constraints\n"\ " dynamic: Transform \"simple\" extended rules, but keep more complex ones", STORE(SELF.erMode), GET((Asp::LogicProgram::ExtendedRuleMode)SELF.erMode)) OPTION(eq, "", ARG(arg("")), "Configure equivalence preprocessing\n" \ " Run for at most %A iterations (-1=run to fixpoint)", STORE_OR_FILL(SELF.iters), GET(SELF.iters)) OPTION(backprop ,"!,@1", ARG(flag()), "Use backpropagation in ASP-preprocessing", STORE_FLAG(SELF.backprop), GET(SELF.backprop)) OPTION(supp_models , ",@1", ARG(flag()), "Compute supported models", STORE_FLAG(SELF.suppMod), GET(SELF.suppMod)) OPTION(no_ufs_check, ",@1", ARG(flag()), "Disable unfounded set check", STORE_FLAG(SELF.noSCC), GET(SELF.noSCC)) OPTION(no_gamma , ",@1", ARG(flag()), "Do not add gamma rules for non-hcf disjunctions", STORE_FLAG(SELF.noGamma), GET(SELF.noGamma)) OPTION(eq_dfs , ",@2", ARG(flag()), "Enable df-order in eq-preprocessing", STORE_FLAG(SELF.dfOrder), GET(SELF.dfOrder)) OPTION(dlp_old_map , ",@3", ARG(flag()), "Enable old mapping for disjunctive LPs", STORE_FLAG(SELF.oldMap), GET(SELF.oldMap)) GROUP_END(SELF) #undef CLASP_ASP_OPTIONS #undef SELF #endif //! Options for the solving algorithm (see Clasp::SolveOptions) #if defined(CLASP_SOLVE_OPTIONS) #define SELF CLASP_SOLVE_OPTIONS GROUP_BEGIN(SELF) OPTION(solve_limit , ",@1", ARG(arg("[,]")), "Stop search after conflicts or restarts\n", FUN(arg) {\ uint32 n = UINT32_MAX; uint32 m = UINT32_MAX;\ return ((arg.off() && arg.peek() != '0') || arg>>n>>opt(m)) && (SELF.limit=SolveLimits(n == UINT32_MAX ? UINT64_MAX : n, m == UINT32_MAX ? UINT64_MAX : m), true);},\ GET((uint32)Range(0u,UINT32_MAX).clamp(SELF.limit.conflicts),(uint32)Range(0u,UINT32_MAX).clamp(SELF.limit.restarts))) #if CLASP_HAS_THREADS OPTION(parallel_mode, ",t", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolveOptions::Algorithm::SearchMode,\ MAP("compete", SolveOptions::Algorithm::mode_compete), MAP("split", SolveOptions::Algorithm::mode_split))),\ "Run parallel search with given number of threads\n" \ " %A: [,]\n" \ " : Number of threads to use in search\n"\ " : Run competition or splitting based search [compete]\n", FUN(arg){\ uint32 n; SolveOptions::Algorithm::SearchMode mode;\ return arg>>n>>opt(mode = SolveOptions::Algorithm::mode_compete) && SET_R(SELF.algorithm.threads, n, 1u, 64u) && SET(SELF.algorithm.mode, mode);},\ GET(SELF.algorithm.threads, (SolveOptions::Algorithm::SearchMode)SELF.algorithm.mode)) OPTION(global_restarts, ",@1", ARG(arg("")), "Configure global restart policy\n" \ " %A: [,]\n" \ " : Maximal number of global restarts (0=disable)\n" \ " : Restart schedule [x,100,1.5] ()\n", FUN(arg) {\ return ITE(arg.off(), (SELF.restarts = SolveOptions::GRestarts(), true), arg>>SELF.restarts.maxR>>opt(SELF.restarts.sched = ScheduleStrategy())\ && SELF.restarts.maxR && SELF.restarts.sched.type != ScheduleStrategy::User);},\ GET_IF(SELF.restarts.maxR, SELF.restarts.maxR, SELF.restarts.sched)) OPTION(distribute, "!,@1", ARG_EXT(defaultsTo("conflict,global,4"), \ DEFINE_ENUM_MAPPING(Distributor::Policy::Types, MAP("all", Distributor::Policy::all), MAP("short", Distributor::Policy::implicit), MAP("conflict", Distributor::Policy::conflict), MAP("loop" , Distributor::Policy::loop))\ DEFINE_ENUM_MAPPING(SolveOptions::Distribution::Mode, MAP("global", SolveOptions::Distribution::mode_global), MAP("local", SolveOptions::Distribution::mode_local))),\ "Configure nogood distribution [%D]\n" \ " %A: [,][,][,]\n" \ " : Distribute {all|short|conflict|loop} nogoods\n" \ " : Use {global|local} distribution [global]\n" \ " : Distribute only if LBD <= [4]\n" \ " : Distribute only if size <= [-1]", \ FUN(arg) { Distributor::Policy::Types type; SolveOptions::Distribution::Mode mode = SolveOptions::Distribution::mode_global; uint32 lbd; uint32 size; \ if (arg.off()) { SELF.distribute.policy() = Distributor::Policy(0, 0, 0); return true; } return (arg >> type) && (arg.peek() < 'A' || arg >> opt(mode)) && arg >> opt(lbd = 4) >> opt(size = UINT32_MAX) && SET(SELF.distribute.types, (uint32)type) && SET(SELF.distribute.mode, (uint32)mode) && SET(SELF.distribute.lbd, lbd) && SET_OR_FILL(SELF.distribute.size, size);},\ GET_FUN(str) { ITE(!SELF.distribute.types, str << off,\ str << (Distributor::Policy::Types)SELF.distribute.types << (SolveOptions::Distribution::Mode)SELF.distribute.mode << SELF.distribute.lbd << SELF.distribute.size); }) OPTION(integrate, ",@1", ARG_EXT(defaultsTo("gp")->state(Value::value_defaulted),\ DEFINE_ENUM_MAPPING(SolveOptions::Integration::Filter, \ MAP("all", SolveOptions::Integration::filter_no), MAP("gp", SolveOptions::Integration::filter_gp),\ MAP("unsat", SolveOptions::Integration::filter_sat), MAP("active", SolveOptions::Integration::filter_heuristic))\ DEFINE_ENUM_MAPPING(SolveOptions::Integration::Topology, \ MAP("all" , SolveOptions::Integration::topo_all) , MAP("ring" , SolveOptions::Integration::topo_ring),\ MAP("cube", SolveOptions::Integration::topo_cube), MAP("cubex", SolveOptions::Integration::topo_cubex))),\ "Configure nogood integration [%D]\n" \ " %A: [,][,]\n" \ " : Add {all|unsat|gp(unsat wrt guiding path)|active} nogoods\n" \ " : Always keep at least last integrated nogoods [1024]\n" \ " : Accept nogoods from {all|ring|cube|cubex} peers [all]\n", FUN(arg) {\ SolveOptions::Integration::Filter pick = SolveOptions::Integration::filter_no; uint32 n; SolveOptions::Integration::Topology topo; return arg>>pick>>opt(n = 1024)>>opt(topo = SolveOptions::Integration::topo_all) && SET(SELF.integrate.filter, (uint32)pick) && SET_OR_FILL(SELF.integrate.grace, n) && SET(SELF.integrate.topo, (uint32)topo);},\ GET((SolveOptions::Integration::Filter)SELF.integrate.filter, SELF.integrate.grace, (SolveOptions::Integration::Topology)SELF.integrate.topo)) #endif OPTION(enum_mode , ",e", ARG_EXT(defaultsTo("auto")->state(Value::value_defaulted), DEFINE_ENUM_MAPPING(SolveOptions::EnumType,\ MAP("bt", SolveOptions::enum_bt), MAP("record", SolveOptions::enum_record), MAP("domRec", SolveOptions::enum_dom_record),\ MAP("brave", SolveOptions::enum_brave), MAP("cautious", SolveOptions::enum_cautious), MAP("query", SolveOptions::enum_query),\ MAP("auto", SolveOptions::enum_auto), MAP("user", SolveOptions::enum_user))),\ "Configure enumeration algorithm [%D]\n" \ " %A: {bt|record|brave|cautious|auto}\n" \ " bt : Backtrack decision literals from solutions\n" \ " record : Add nogoods for computed solutions\n" \ " domRec : Add nogoods over true domain atoms\n" \ " brave : Compute brave consequences (union of models)\n" \ " cautious: Compute cautious consequences (intersection of models)\n" \ " auto : Use bt for enumeration and record for optimization", STORE(SELF.enumMode), GET(SELF.enumMode)) OPTION(project, "!", ARG_EXT(arg("")->implicit("auto,3"), DEFINE_ENUM_MAPPING(ProjectMode_t::Mode,\ MAP("auto", ProjectMode_t::Implicit), MAP("show", ProjectMode_t::Output), MAP("project", ProjectMode_t::Explicit))),\ "Enable projective solution enumeration\n" \ " %A: {show|project|auto}[,] (Implicit: %I)\n" \ " Project to atoms in show or project directives, or\n" \ " select depending on the existence of a project directive\n" \ " : Additional options for enumeration algorithm 'bt'\n" \ " Use activity heuristic (1) when selecting backtracking literal\n" \ " and/or progress saving (2) when retracting solution literals", \ FUN(arg) { ProjectMode m = ProjectMode_t::Implicit; uint32 p = 0; \ return (arg.off() || (arg.peek() < '9' && arg >> p) || ((arg >> m >> opt(p)) && (p = (p<<1)|1) != 0u)) && SET(SELF.proMode, m) && SET_LEQ(SELF.project, p, 7u);},\ GET_IF(SELF.project, SELF.proMode, SELF.project >> 1)) OPTION(models, ",n", ARG(arg("")), "Compute at most %A models (0 for all)\n", STORE(SELF.numModels), GET(SELF.numModels)) OPTION(opt_mode , "", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(MinimizeMode_t::Mode,\ MAP("opt" , MinimizeMode_t::optimize), MAP("enum" , MinimizeMode_t::enumerate),\ MAP("optN", MinimizeMode_t::enumOpt) , MAP("ignore", MinimizeMode_t::ignore))),\ "Configure optimization algorithm\n"\ " %A: [,...]\n" \ " opt : Find optimal model\n" \ " enum : Find models with costs <= \n" \ " optN : Find optimum, then enumerate optimal models\n"\ " ignore: Ignore optimize statements\n" \ " : Set initial bound for objective function(s)", \ FUN(arg) { MinimizeMode_t::Mode m = MinimizeMode_t::optimize; SumVec B; return (arg >> m >> opt(B)) && SET(SELF.optMode, m) && (SELF.optBound.swap(B), true); }, \ GET_FUN(str) { str << SELF.optMode; if (!SELF.optBound.empty()) str << SELF.optBound; }) GROUP_END(SELF) #undef CLASP_SOLVE_OPTIONS #undef SELF #endif #undef GROUP_BEGIN #undef GROUP_END #undef OPTION #undef NOTIFY_SUBGROUPS #undef ARG #undef ARG_EXT #undef NO_ARG clingo-5.2.2/clasp/clasp/cli/clasp_options.h000066400000000000000000000277411320011352300207750ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_CLI_CLASP_OPTIONS_H_INCLUDED #define CLASP_CLI_CLASP_OPTIONS_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include namespace Potassco { namespace ProgramOptions { class OptionContext; class OptionGroup; class ParsedOptions; }} /*! * \file * \brief Types and functions for processing command-line options. */ namespace Clasp { //! Namespace for types and functions used by the command-line interface. namespace Cli { /** * \defgroup cli Cli * \brief Types mainly relevant to the command-line interface. * \ingroup facade * @{ */ class ClaspCliConfig; //! Class for iterating over a set of configurations. class ConfigIter { public: const char* name() const; const char* base() const; const char* args() const; bool valid()const; bool next(); private: friend class ClaspCliConfig; ConfigIter(const char* x); const char* base_; }; //! Valid configuration keys. /*! * \see clasp_cli_configs.inl */ enum ConfigKey { #define CONFIG(id,k,c,s,p) config_##k, #define CLASP_CLI_DEFAULT_CONFIGS config_default = 0, #define CLASP_CLI_AUX_CONFIGS config_default_max_value, #include config_aux_max_value, config_many, // default portfolio config_max_value, config_asp_default = config_tweety, config_sat_default = config_trendy, config_tester_default= config_tester, }; /*! * \brief Class for storing/processing command-line options. * * Caveats (when using incrementally, e.g. from clingo): * - supp-models: State Transition (yes<->no) not supported. * - supp-models=yes is irreversible for a step * because it enables possibly destructive simplifications * and skips SCC-checking (i.e. new SCCs are silently discarded). * - Nogoods learnt during supp-models=no are not tagged and * hence can't simply be removed on transition to yes. * . * - stats: Stats level can only be increased. * - A stats level once activated stays activated even if * level is subsequently decreased via option. * . * - save-progress, sign-fix, opt-heuristic: No unset of previously set values. * - Once set, signs are only unset if forgetOnStep includes sign. * . * - no-lookback: State Transition (yes<->no) not supported. * - noLookback=yes is a destructive meta-option that disables lookback-options by changing their value * - noLookback=no does not re-enable those options. * . */ class ClaspCliConfig : public ClaspConfig { public: //! Returns defaults for the given problem type. static const char* getDefaults(ProblemType f); //! Returns the configuration with the given key. static ConfigIter getConfig(ConfigKey key); //! Returns the ConfigKey of k or -1 if k is not a known configuration. static int getConfigKey(const char* k); ClaspCliConfig(); ~ClaspCliConfig(); // Base interface virtual void prepare(SharedContext&); virtual void reset(); virtual Configuration* config(const char*); /*! * \name Key-based low-level interface * * The functions in this group do not throw exceptions but * signal logic errors via return values < 0. * @{ */ typedef uint32 KeyType; static const KeyType KEY_INVALID; //!< Invalid key used to signal errors. static const KeyType KEY_ROOT; //!< Root key of a configuration, i.e. "." static const KeyType KEY_TESTER; //!< Root key for tester options, i.e. "tester." static const KeyType KEY_SOLVER; //!< Root key for (array of) solver options, i.e. "solver." //! Returns true if k is a leaf, i.e. has no subkeys. static bool isLeafKey(KeyType k); //! Retrieves a handle to the specified key. /*! * \param key A valid handle to a key. * \param name The name of the subkey to retrieve. * \return * - key, if name is 0 or empty. * - KEY_INVALID, if name is not a subkey of key. * - A handle to the subkey. * . */ KeyType getKey(KeyType key, const char* name = 0) const; //! Retrieves a handle to the specified element of the given array key. /*! * \param arr A valid handle to an array. * \param element The index of the element to retrieve. * \return * - A handle to the requested element, or * - KEY_INVALID, if arr does not reference an array or element is out of bounds. * . */ KeyType getArrKey(KeyType arr, unsigned element) const; //! Retrieves information about the specified key. /*! * \param key A valid handle to a key. * \param[out] nSubkeys The number of subkeys of this key or 0 if key is a leaf. * \param[out] arrLen If key is an array, the length of the array (can be 0). Otherwise, -1. * \param[out] help A description of the key. * \param[out] nValues The number of values the key currently has (0 or 1) or -1 if it can't have values. * \note All out parameters are optional, i.e. can be 0. * \return The number of out values or -1 if key is invalid. */ int getKeyInfo(KeyType key, int* nSubkeys = 0, int* arrLen = 0, const char** help = 0, int* nValues = 0) const; //! Returns the name of the i'th subkey of k or 0 if no such subkey exists. const char* getSubkey(KeyType k, uint32 i) const; //! Creates and returns a string representation of the value of the given key. /*! * \param k A valid handle to a key. * \param[out] value The current value of the key. * \return The length of value or < 0 if k either has no value (-1) or an error occurred while writing the value (< -1). */ int getValue(KeyType k, std::string& value) const; //! Writes a null-terminated string representation of the value of the given key into the supplied buffer. /*! * \param k A valid handle to a key. * \param[out] buffer The current value of the key. * \param bufSize The size of buffer. * \note Although the number returned can be larger than the bufSize, the function * never writes more than bufSize bytes into the buffer. */ int getValue(KeyType k, char* buffer, std::size_t bufSize) const; //! Sets the option identified by the given key. /*! * \param key A valid handle to a key. * \param value The value to set. * \return * - > 0: if the value was set. * - = 0: if value is not a valid value for the given key. * - < 0: f key does not accept a value (-1), or some error occurred (< -1). * . */ int setValue(KeyType key, const char* value); //@} /*! * \name String-based interface * * The functions in this group wrap the key-based functions and * signal logic errors by throwing exceptions. * @{ */ //! Returns the value of the option identified by the given key. std::string getValue(const char* key) const; //! Returns true if the given key has an associated value. bool hasValue(const char* key) const; //! Sets the option identified by the given key. bool setValue(const char* key, const char* value); //@} //! Validates this configuration. bool validate(); /*! * \name App interface * * Functions for connecting a configuration with the ProgramOptions library. * @{ */ //! Adds all available options to root. /*! * Once options are added, root can be used with an option source (e.g. the command-line) * to populate this object. */ void addOptions(Potassco::ProgramOptions::OptionContext& root); //! Adds options that are disabled by the options contained in parsed to parsed. void addDisabled(Potassco::ProgramOptions::ParsedOptions& parsed); //! Applies the options in parsed and finalizes and validates this configuration. bool finalize(const Potassco::ProgramOptions::ParsedOptions& parsed, ProblemType type, bool applyDefaults); //! Populates this configuration with the options given in [first, last) and finalizes it. /*! * \param [first, last) a range of options in argv format. * \param t Problem type for which this configuration is created. Used to set defaults. */ template bool setConfig(IT first, IT last, ProblemType t) { RawConfig config("setConfig"); while (first != last) { config.addArg(*first++); } return setAppConfig(config, t); } //! Releases internal option objects needed for command-line style option processing. /*! * \note Subsequent calls to certain functions of this object (e.g. addOptions(), setConfig()) * recreate the option objects if necessary. */ void releaseOptions(); //@} private: static const uint8 mode_solver = 1u; static const uint8 mode_tester = 2u; static const uint8 mode_relaxed= 4u; struct ParseContext; struct OptIndex; class ProgOption; typedef Potassco::ProgramOptions::OptionContext OptionContext; typedef Potassco::ProgramOptions::OptionGroup Options; typedef SingleOwnerPtr OptionsPtr; typedef PodVector::type ConfigVec; typedef Potassco::ProgramOptions::ParsedOptions ParsedOpts; struct ScopedSet { ScopedSet(ClaspCliConfig& s, uint8 mode, uint32 sId = 0); ~ScopedSet(); ClaspCliConfig* operator->()const { return self; } ClaspCliConfig* self; }; struct RawConfig { std::string raw; explicit RawConfig(const char* name); void addArg(const char* arg); void addArg(const std::string& arg); ConfigIter iterator() const { return ConfigIter(raw.data()); } }; // Operations on active config and solver int setActive(int o, const char* value); int getActive(int o, std::string* value, const char** desc, const char** opt) const; int applyActive(int o, const char* setValue, std::string* getValue, const char** getDesc, const char** name); // App interface impl bool setAppConfig(const RawConfig& c, ProblemType t); int setAppOpt(int o, const char* value); bool setAppDefaults(UserConfig* active, uint32 sId, const ParsedOpts& exclude, ProblemType t); bool finalizeAppConfig(UserConfig* active, const ParsedOpts& exclude, ProblemType t, bool defs); const ParsedOpts& finalizeParsed(UserConfig* active, const ParsedOpts& parsed, ParsedOpts& exclude) const; void createOptions(); ProgOption* createOption(int o); bool assignDefaults(const ParsedOpts&); // Configurations static bool appendConfig(std::string& to, const std::string& line); static bool loadConfig(std::string& to, const char* fileName); ConfigIter getConfig(uint8 key, std::string& tempMem); bool setConfig(const ConfigIter& it, bool allowAppOpt, const ParsedOpts& exclude, ParsedOpts* out); // helpers bool isGenerator() const { return (cliMode & mode_tester) == 0; } const UserConfig*active()const { return isGenerator() ? this : testerConfig(); } UserConfig* active() { return isGenerator() ? this : testerConfig(); } bool match(const char*& path, const char* what) const; static OptIndex index_g; OptionsPtr opts_; std::string config_[2]; bool initTester_; }; //! Validates the given solver configuration and returns an error string if invalid. const char* validate(const SolverParams& solver, const SolveParams& search); //@} }} #endif clingo-5.2.2/clasp/clasp/cli/clasp_output.h000066400000000000000000000264711320011352300206410ustar00rootroot00000000000000// // Copyright (c) 2009-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_CLI_OUTPUT_H_INCLUDED #define CLASP_CLI_OUTPUT_H_INCLUDED #include #include #include #include namespace Clasp { namespace Cli { template void formatEvent(const T& eventType, S& str); template void format(const Clasp::Event_t& ev, S& str) { formatEvent(static_cast(ev), str); } /*! * \addtogroup cli * @{ */ /*! * \brief Interface for printing status and input format dependent information, * like models, optimization values, and summaries. */ class Output : public EventHandler { public: //! Supported levels for printing models, optimize values, and individual calls. enum PrintLevel { print_all = 0, //!< Print all models, optimize values, or calls. print_best = 1, //!< Only print last model, optimize value, or call. print_no = 2, //!< Do not print any models, optimize values, or calls. }; explicit Output(uint32 verb = 1); virtual ~Output(); //! Active verbosity level. uint32 verbosity() const { return verbose_; } //! Do not output any models? bool quiet() const { return modelQ() == 2 && optQ() == 2; } //! Print level for models. int modelQ() const { return static_cast(quiet_[0]); } //! Print level for optimization values. int optQ() const { return static_cast(quiet_[1]); } //! Print level for individual (solve) calls. int callQ() const { return static_cast(quiet_[2]); } using EventHandler::setVerbosity; void setVerbosity(uint32 verb); void setModelQuiet(PrintLevel model); void setOptQuiet(PrintLevel opt); void setCallQuiet(PrintLevel call); //! Shall be called once on startup. virtual void run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput) = 0; //! Shall be called once on shutdown. virtual void shutdown(const ClaspFacade::Summary& summary); virtual void shutdown() = 0; //! Handles ClaspFacade events by forwarding calls to startStep() and stopStep(). virtual void onEvent(const Event& ev); //! Checks quiet-levels and forwards to printModel() if appropriate. virtual bool onModel(const Solver& s, const Model& m); //! Checks quiet-levels and forwards to printLower() if appropriate. virtual bool onUnsat(const Solver& s, const Model& m); //! Shall print the given model. virtual void printModel(const OutputTable& out, const Model& m, PrintLevel x) = 0; //! Called on unsat - may print new info. virtual void printUnsat(const OutputTable& out, const LowerBound* lower, const Model* prevModel); //! A solving step has started. virtual void startStep(const ClaspFacade&); //! A solving step has stopped. virtual void stopStep(const ClaspFacade::Summary& summary); //! Shall print the given summary. virtual void printSummary(const ClaspFacade::Summary& summary, bool final) = 0; //! Shall print the given statistics. virtual void printStatistics(const ClaspFacade::Summary& summary, bool final) = 0; protected: typedef std::pair OutPair; typedef uintp UPtr; typedef std::pair UPair; const Model* getModel() const { return saved_.values ? &saved_ : 0; } void saveModel(const Model& m); void clearModel() { saved_.reset(); } void printWitness(const OutputTable& out, const Model& m, UPtr data); virtual UPtr doPrint(const OutPair& out, uintp data); UPair numCons(const OutputTable& out, const Model& m) const; bool stats(const ClaspFacade::Summary& summary) const; private: Output(const Output&); Output& operator=(const Output&); typedef const ClaspFacade::Summary* SumPtr ; SumPtr summary_ ; // summary of last step ValueVec vals_ ; // saved values from most recent model SumVec costs_ ; // saved costs from most recent model Model saved_ ; // most recent model uint32 verbose_ ; // verbosity level uint8 quiet_[3]; // quiet levels for models, optimize, calls }; //! Prints models and solving statistics in Json-format to stdout. class JsonOutput : public Output, private StatsVisitor { public: explicit JsonOutput(uint32 verb); ~JsonOutput(); virtual void run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput); virtual void shutdown(const ClaspFacade::Summary& summary); virtual void shutdown(); virtual void printSummary(const ClaspFacade::Summary& summary, bool final); virtual void printStatistics(const ClaspFacade::Summary& summary, bool final); private: virtual void startStep(const ClaspFacade&); virtual void stopStep(const ClaspFacade::Summary& summary); virtual bool visitThreads(Operation op); virtual bool visitTester(Operation op); virtual bool visitHccs(Operation op); virtual void visitThread(uint32, const SolverStats& stats); virtual void visitHcc(uint32, const ProblemStats& p, const SolverStats& s); virtual void visitLogicProgramStats(const Asp::LpStats& stats); virtual void visitProblemStats(const ProblemStats& stats); virtual void visitSolverStats(const SolverStats& stats); virtual UPtr doPrint(const OutPair& out, UPtr data); enum ObjType { type_object, type_array }; void pushObject(const char* k = 0, ObjType t = type_object); char popObject(); void printKeyValue(const char* k, const char* v) ; void printKeyValue(const char* k, uint64 v); void printKeyValue(const char* k, uint32 v); void printKeyValue(const char* k, double d); void printString(const char* s, const char* sep); void printKey(const char* k); void printModel(const OutputTable& out, const Model& m, PrintLevel x); void printCosts(const SumVec& costs, const char* name = "Costs"); void printCons(const UPair& cons); void printCoreStats(const CoreStats&); void printExtStats(const ExtendedStats&, bool generator); void printJumpStats(const JumpStats&); void startModel(); bool hasWitness() const { return !objStack_.empty() && *objStack_.rbegin() == '['; } uint32 indent() const { return static_cast(objStack_.size() * 2); } const char* open_; std::string objStack_; }; //! Default clasp format printer. /*! * Prints all output to stdout in given format: * - format_asp prints in clasp's default asp format * - format_aspcomp prints in in ASP competition format * - format_sat09 prints in SAT-competition format * - format_pb09 in PB-competition format * . * \see https://www.mat.unical.it/aspcomp2013/ * \see http://www.satcompetition.org/2009/format-solvers2009.html * \see http://www.cril.univ-artois.fr/PB09/solver_req.html * */ class TextOutput : public Output, private StatsVisitor { public: //! Supported text formats. enum Format { format_asp, format_aspcomp, format_sat09, format_pb09 }; enum ResultStr { res_unknonw = 0, res_sat = 1, res_unsat = 2, res_opt = 3, num_str }; enum CategoryKey { cat_comment, cat_value, cat_objective, cat_result, cat_value_term, cat_atom_name, cat_atom_var, num_cat }; const char* result[num_str]; //!< Default result strings. const char* format[num_cat]; //!< Format strings. TextOutput(uint32 verbosity, Format f, const char* catAtom = 0, char ifs = ' '); ~TextOutput(); //! Prints a (comment) message containing the given solver and input. virtual void run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput); virtual void shutdown(); //! Prints the given model. /*! * Prints format[cat_value] followed by the elements of the model. Individual * elements e are printed as format[cat_atom] and separated by the internal field separator. */ virtual void printModel(const OutputTable& out, const Model& m, PrintLevel x); //! Prints the given lower bound and upper bounds that are known to be optimal. virtual void printUnsat(const OutputTable& out, const LowerBound* lower, const Model* prevModel); //! Called once a solving step has completed. /*! * Always prints "format[cat_result] result[s.result()]". * Furthermore, if verbosity() > 0, prints a summary consisting of * - the number of computed models m and whether the search space was exhausted * - the number of enumerated models e if e != m * - the state of any optimization and whether the last model was optimal * - the state of consequence computation and whether the last model corresponded to the consequences * - timing information * . */ virtual void printSummary(const ClaspFacade::Summary& s , bool final); virtual void printStatistics(const ClaspFacade::Summary& s, bool final); //! Prints progress events (preprocessing/solving) if verbosity() > 1. virtual void onEvent(const Event& ev); //! A solving step has started. virtual void startStep(const ClaspFacade&); //! Prints a comment message. void comment(uint32 v, const char* fmt, ...) const; protected: virtual bool visitThreads(Operation op); virtual bool visitTester(Operation op); virtual void visitThread(uint32, const SolverStats& stats); virtual void visitHcc(uint32, const ProblemStats& p, const SolverStats& s); virtual void visitLogicProgramStats(const Asp::LpStats& stats); virtual void visitProblemStats(const ProblemStats& stats); virtual void visitSolverStats(const SolverStats& stats); virtual UPtr doPrint(const OutPair& out, UPtr data); const char* fieldSeparator() const; int printSep(CategoryKey c) const; void printCosts(const SumVec&) const; void printBounds(const SumVec& upper, const SumVec& lower) const; void printStats(const SolverStats& stats) const; void printJumps(const JumpStats&) const; bool startSection(const char* n) const; void startObject(const char* n, uint32 i) const; void setState(uint32 state, uint32 verb, const char* st); void printSolveProgress(const Event& ev); void printValues(const OutputTable& out, const Model& m); void printMeta(const OutputTable& out, const Model& m); private: typedef Clasp::Atomic_t::type EvType; std::string fmt_; double stTime_;// time on state enter EvType ev_; // last event type int width_; // output width int line_; // lines to print until next separator uint32 state_; // active state char ifs_[2];// field separator bool accu_; }; //@} }} #endif clingo-5.2.2/clasp/clasp/clingo.h000066400000000000000000000147071320011352300166220ustar00rootroot00000000000000// // Copyright (c) 2015-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_CLINGO_H_INCLUDED #define CLASP_CLINGO_H_INCLUDED /*! * \file * \brief Types for implementing theory propagation from clingo. */ #include #include namespace Clasp { /*! * \defgroup clingo Clingo * \brief Additional classes mainly used by clingo. * \ingroup facade * @{ */ //! Lock interface called by libclasp during (multi-threaded) theory propagation. /*! * The interface may be implemented by the application to lock * certain global data structures. For example, in clingo, * this interface wraps python's global interpreter lock. */ class ClingoPropagatorLock { public: virtual ~ClingoPropagatorLock(); virtual void lock() = 0; virtual void unlock() = 0; }; //! Supported check modes for clingo propagators. struct ClingoPropagatorCheck_t { enum Type { No = 0u, //!< Never call AbstractPropagator::check(). Total = 1u, //!< Call AbstractPropagator::check() only on total assignment. Fixpoint = 2u //!< Call AbstractPropagator::check() on every propagation fixpoint. }; }; //! Initialization adaptor for a Potassco::AbstractPropagator. /*! * The class provides a function for registering watches for the propagator. * Furthermore, it can be added to a clasp configuration so that * a (suitably adapted) propagator is added to solvers that are attached to the configuration. */ class ClingoPropagatorInit : public ClaspConfig::Configurator { public: typedef ClingoPropagatorCheck_t::Type CheckType; //! Creates a new adaptor. /*! * \param cb The (theory) propagator that should be added to solvers. * \param lock An optional lock that should be applied during theory propagation. * * If lock is not null, calls to cb are wrapped in a lock->lock()/lock->unlock() pair */ ClingoPropagatorInit(Potassco::AbstractPropagator& cb, ClingoPropagatorLock* lock = 0, CheckType check = ClingoPropagatorCheck_t::Total); ~ClingoPropagatorInit(); // base class virtual void prepare(SharedContext&); //! Adds a ClingoPropagator adapting the propagator() to s. virtual bool addPost(Solver& s); // for clingo //! Sets the type of checks to enable during solving. /*! * \param checkMode A set of ClingoPropagatorCheck_t::Type values. */ void enableClingoPropagatorCheck(CheckType checkMode); //! Registers a watch for lit and returns encodeLit(lit). Potassco::Lit_t addWatch(Literal lit); //! Returns the propagator that was given on construction. Potassco::AbstractPropagator* propagator() const { return prop_; } ClingoPropagatorLock* lock() const { return lock_; } const LitVec& watches() const { return watches_; } CheckType checkMode() const { return check_; } private: ClingoPropagatorInit(const ClingoPropagatorInit&); ClingoPropagatorInit& operator=(const ClingoPropagatorInit&); Potassco::AbstractPropagator* prop_; ClingoPropagatorLock* lock_; LitVec watches_; VarVec seen_; CheckType check_; }; //! Adaptor for a Potassco::AbstractPropagator. /*! * The class adapts a given Potassco::AbstractPropagator so that * it is usable as a PostPropagator within libclasp. * \note This class is meant to be a final class. */ class ClingoPropagator : public Clasp::PostPropagator { public: typedef Potassco::AbstractPropagator::ChangeList ChangeList; typedef Clasp::PostPropagator::PropResult PPair; explicit ClingoPropagator(ClingoPropagatorInit* init); // PostPropagator virtual uint32 priority() const; virtual bool init(Solver& s); virtual bool propagateFixpoint(Clasp::Solver& s, Clasp::PostPropagator* ctx); virtual PPair propagate(Solver&, Literal, uint32&); virtual bool isModel(Solver& s); virtual void reason(Solver&, Literal, LitVec&); virtual void undoLevel(Solver& s); virtual bool simplify(Solver& s, bool reinit); virtual void destroy(Solver* s, bool detach); private: typedef LitVec::size_type size_t; typedef Potassco::Lit_t Lit_t; class Control; enum State { state_ctrl = 1u, state_prop = 2u }; struct ClauseTodo { bool empty() const { return mem.empty(); } void clear() { mem.clear(); } LitVec mem; ClauseRep clause; uint32 flags; }; typedef PodVector::type AspifVec; typedef PodVector::type ClauseDB; typedef ClingoPropagatorInit Propagator; typedef ClingoPropagatorLock* ClingoLock; typedef const LitVec& Watches; bool addClause(Solver& s, uint32 state); void toClause(Solver& s, const Potassco::LitSpan& clause, Potassco::Clause_t prop); void registerUndo(Solver& s); Propagator* call_; // wrapped theory propagator AspifVec trail_; // assignment trail: watched literals that are true AspifVec temp_; // temporary buffer used to pass changes to user VarVec undo_; // offsets into trail marking beginnings of decision levels ClauseDB db_; // clauses added with flag static ClauseTodo todo_; // active clause to be added (received from theory propagator) size_t init_; // offset into watches separating old and newly added ones size_t prop_; // offset into trail: literals [0, prop_) were propagated size_t epoch_; // number of calls into callback uint32 level_; // highest undo level int32 front_; // global assignment position for fixpoint checks Literal aux_; // max active literal }; ///@} } #endif clingo-5.2.2/clasp/clasp/config.h.in000066400000000000000000000054141320011352300172140ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //! \file //! \brief Active configuration. #ifndef CLASP_CONFIG_H_INCLUDED #define CLASP_CONFIG_H_INCLUDED #ifdef _MSC_VER #pragma once #endif //! Library version. #define CLASP_VERSION "@CLASP_VERSION@" #define CLASP_VERSION_MAJOR @CLASP_VERSION_MAJOR@ #define CLASP_VERSION_MINOR @CLASP_VERSION_MINOR@ #define CLASP_VERSION_PATCH @CLASP_VERSION_PATCH@ #define CLASP_LEGAL "Copyright (C) Benjamin Kaufmann" //! Single or multi-threaded version of clasp. #cmakedefine01 CLASP_HAS_THREADS //! Use std::vector instead of pod_vector. #define CLASP_USE_STD_VECTOR @CLASP_USE_STD_VECTOR@ #include #if CLASP_HAS_THREADS #include #endif namespace Clasp { @CLASP_DEFINE_ATOMIC@ template struct Atomic_t { typedef @CLASP_ATOMIC_TYPE@ type; }; template T compare_and_swap(@CLASP_ATOMIC_TYPE@& in, T oldVal, T newVal) { in.compare_exchange_strong(oldVal, newVal); return oldVal; } typedef uint64_t uint64; typedef uint32_t uint32; typedef uint16_t uint16; typedef uint8_t uint8; typedef uintptr_t uintp; typedef int64_t int64; typedef int32_t int32; typedef int16_t int16; typedef int8_t int8; inline void* alignedAlloc(size_t size, size_t align) { #if defined(__CYGWIN__) return memalign(align, size); #elif defined(_WIN32) || defined(_WIN64) return _aligned_malloc(size, align); #else void* result = 0; return posix_memalign(&result, align, size) == 0 ? result : static_cast(0); #endif } inline void alignedFree(void* p) { #if defined(_WIN32) || defined(_WIN64) _aligned_free(p); #else free(p); #endif } } // namespace Clasp #endif clingo-5.2.2/clasp/clasp/constraint.h000066400000000000000000000530221320011352300175240ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_CONSTRAINT_H_INCLUDED #define CLASP_CONSTRAINT_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include // bits stuff #include /*! * \file * \brief Defines the base classes for boolean constraints. */ namespace Clasp { class SharedContext; class Solver; class ClauseHead; struct CCMinRecursive; /** * \defgroup constraint Constraints * \brief Boolean Constraints, post propagators, and related types. * @{ */ //! Constraint types distinguished by a Solver. struct Constraint_t { enum Type { Static = 0, //!< An unremovable constraint (e.g. a problem constraint). Conflict = 1, //!< A removable constraint derived from conflict analysis. Loop = 2, //!< A removable constraint derived from unfounded set checking. Other = 3, //!< A removable constraint learnt by some other means. Type__max = Other }; struct Set { Set() : m(0) {} bool inSet(Type t) const { return (m & (uint32(1)<[priority_class_simple, priority_class_general) * - class_general: post propagators that are non-deterministic or those that are not limited to extending * the current decision level shall have a priority of priority_class_general. They are called in FIFO order * after \b all simple post propagators have reached a fixpoint. * * \note There are currently three reserved priority values, namely * - priority_reserved_msg for message and termination handler (if any), * - priority_reserved_ufs for the default unfounded set checker (if any), * - and priority_reserved_look for the default lookahead operator (if any). * . */ class PostPropagator : public Constraint { public: PostPropagator(); virtual ~PostPropagator(); using Constraint::propagate; // Enable overloading! PostPropagator* next; // main propagation lists of post propagators //! Default priorities for post propagators. enum Priority { priority_class_simple = 0, //!< Starting priority of simple post propagators. priority_reserved_msg = 0, //!< Reserved priority for message/termination handlers (if any). priority_reserved_ufs = 10, //!< Reserved priority for the default unfounded set checker (if any). priority_reserved_look = 1023, //!< Reserved priority for the default lookahead operator (if any). priority_class_general = 1024, //!< Priortiy of extended post propagators. }; //! Shall return a value representing the priority of this propagator. /*! * The priority is used to order sequences of post propagators and to * classify post propagators w.r.t the classes: class_simple and class_general. * \note See class description for an overview of the two priority classes. */ virtual uint32 priority() const = 0; //! Called during initialization of s. /*! * \note During initialization a post propagator may assign variables * but it must not yet propagate them. */ virtual bool init(Solver& s); //! Shall enqueue and propagate new assignments implied by this propagator. /*! * This function shall enqueue and propagate all assignments currently implied by * this propagator until a fixpoint is reached w.r.t this post propagator or * a conflict is detected. * * \pre The assignment is fully propagated w.r.t any previous post propagator. * \param s The solver in which this post propagator is used. * \param ctx The post propagator from which this post propagator is called or * 0 if no other post propagator is currently active. * \post s.queueSize() == 0 || s.hasConflict() * \return false if propagation led to conflict, true otherwise * * \note * The function shall not call Solver::propagate() * or any other function that would result in a recursive chain * of propagate() calls. On the other hand, it shall call * Solver::propagateUntil(this) after enqueuing any new assignments * to initiate propagation up to this propagator. * * Typically, propagateFixpoint() should implemet a loop like this: * \code * for (;;) { * if (!assign_newly_implied_literals(s)){ return false; } * if (s.queueSize() == 0) { return true; } * if (!s.propagateUntil(this)) { return false; } * } * \endcode */ virtual bool propagateFixpoint(Solver& s, PostPropagator* ctx) = 0; //! Aborts an active propagation operation. /*! * The function reset() is called whenever propagation on the * current decision level is stopped before a fixpoint is reached. * In particular, a solver calls reset() when a conflict is detected * during propagation. * * \note The default implementation is a noop. */ virtual void reset(); //! Is the current total assignment a model? /*! * \pre The assignment is total and not conflicting. * \return * - true if the assignment is a model w.r.t this post propagator * - false otherwise * \post If the function returned true: s.numFreeVars() == 0 && !s.hasConflict(). * If the function returned false: s.numFreeVars() > 0 || s.hasConflict(). * \note The default implementation returns Constraint::valid(s); */ virtual bool isModel(Solver& s); protected: //! Calls reset on post propagators following this. void cancelPropagation(); //! PostPropagators are not clonable by default. Constraint* cloneAttach(Solver&) { return 0; } // Constraint interface - noops PropResult propagate(Solver&, Literal, uint32&); void reason(Solver&, Literal, LitVec& ); private: PostPropagator(const PostPropagator&); PostPropagator& operator=(const PostPropagator&); }; //! A special post propagator used to handle messages and signals. class MessageHandler : public PostPropagator { public: MessageHandler(); virtual bool handleMessages() = 0; virtual uint32 priority()const { return PostPropagator::priority_reserved_msg; } virtual bool propagateFixpoint(Solver&, PostPropagator*) { return handleMessages(); } }; //! An intrusive list of post propagators ordered by priority. /*! * Propagators in the list are owned by the list. */ class PropagatorList { public: PropagatorList(); ~PropagatorList(); void add(PostPropagator* p); void remove(PostPropagator* p); void clear(); PostPropagator* find(uint32 prio) const; PostPropagator*const* head() const { return &head_; } PostPropagator** head() { return &head_; } private: PropagatorList(const PropagatorList&); PropagatorList& operator=(const PropagatorList&); PostPropagator* head_;// head of pp-list }; //@} /** * \addtogroup constraint * @{ */ //! Stores a reference to the constraint that implied a literal. /*! * Stores a reference to the constraint that implied a certain literal or * null if the literal has no antecedent (i.e. is a decision literal or a top-level fact). * * \note * The constraint that implied a literal can have three different representations: * - it can be a single literal (binary clause constraint) * - it can be two literals (ternary clause constraint) * - it can be a pointer to a constraint (generic constraint) * . * * \par Implementation: * * The class stores all three representations in one tagged 64-bit integer, i.e. * from the 64-bits the 2 LSBs encode the type stored: * - 00: Pointer to constraint * - 01: ternary constraint (i.e. two literals stored in the remaining 62 bits). * - 10: binary constraint (i.e. one literal stored in the highest 31 bits) * . */ class Antecedent { public: enum Type { Generic = 0, Ternary = 1, Binary = 2}; //! Creates a null Antecedent. /*! * \post: isNull() == true && type == Generic */ Antecedent() : data_(0) {} //! Creates an Antecedent from the literal p. /*! * \post: type() == Binary && firstLiteral() == p */ Antecedent(const Literal& p) { // first lit is stored in high dword data_ = (((uint64)p.id()) << 33) + Binary; assert(type() == Binary && firstLiteral() == p); } //! Creates an Antecedent from the literals p and q. /*! * \post type() == Ternary && firstLiteral() == p && secondLiteral() == q */ Antecedent(const Literal& p, const Literal& q) { // first lit is stored in high dword // second lit is stored in low dword data_ = (((uint64)p.id()) << 33) + (((uint64)q.id()) << 2) + Ternary; assert(type() == Ternary && firstLiteral() == p && secondLiteral() == q); } //! Creates an Antecedent from the Constraint con. /*! * \post type() == Generic && constraint() == con */ Antecedent(Constraint* con) : data_((uintp)con) { static_assert(sizeof(Constraint*) <= sizeof(uint64), "unsupported pointer size"); assert(type() == Generic && constraint() == con); } //! Returns true if this antecedent does not refer to any constraint. bool isNull() const { return data_ == 0; } //! Returns the antecedent's type. Type type() const { return Type( data_ & 3 ); } //! Returns true if the antecedent is a learnt nogood. bool learnt() const { return data_ && (data_ & 3u) == 0 && constraint()->type() != Constraint_t::Static; } //! Extracts the constraint-pointer stored in this object. /*! * \pre type() == Generic */ Constraint* constraint() const { assert(type() == Generic); return (Constraint*)(uintp)data_; } //! Extracts the first literal stored in this object. /*! * \pre type() != Generic */ Literal firstLiteral() const { assert(type() != Generic); return Literal::fromId(static_cast(data_ >> 33)); } //! Extracts the second literal stored in this object. /*! * \pre type() == Ternary */ Literal secondLiteral() const { assert(type() == Ternary); return Literal::fromId( static_cast(data_>>1) >> 1 ); } //! Returns the reason for p. /*! * \pre !isNull() */ void reason(Solver& s, Literal p, LitVec& lits) const { assert(!isNull()); Type t = type(); if (t == Generic) { constraint()->reason(s, p, lits); return; } lits.push_back(firstLiteral()); if (t == Ternary) { lits.push_back(secondLiteral()); } } template bool minimize(S& s, Literal p, CCMinRecursive* rec) const { assert(!isNull()); Type t = type(); if (t == Generic) { return constraint()->minimize(s, p, rec); } return s.ccMinimize(firstLiteral(), rec) && (t != Ternary || s.ccMinimize(secondLiteral(), rec)); } //! Returns true iff the antecedent refers to the constraint con. bool operator==(const Constraint* con) const { return static_cast(data_) == reinterpret_cast(con); } uint64 asUint() const { return data_; } uint64& asUint() { return data_; } private: uint64 data_; }; enum { LBD_MAX = 127u, ACT_MAX = (1u << 20) - 1 }; //! Type storing a constraint's activity. struct ConstraintScore { typedef ConstraintScore Score; enum { LBD_SHIFT = 20, BMP_BIT = 27, BITS_USED = 28, LBD_MASK = LBD_MAX<> LBD_SHIFT) : uint32(LBD_MAX); } bool hasLbd() const { return (rep & LBD_MASK) != 0; } bool bumped() const { return test_bit(rep, BMP_BIT); } void bumpActivity() { if (activity() < uint32(ACT_MAX)) ++rep; } void bumpLbd(uint32 x) { if (x < lbd()) { rep &= ~uint32(LBD_MASK); rep |= (x << LBD_SHIFT) | bit_mask(BMP_BIT); } } void clearBumped() { store_clear_bit(rep, BMP_BIT); } void reduce() { clearBumped(); if (uint32 a = activity()) { rep &= ~uint32(ACT_MAX); rep |= (a>>1); } } void assign(Score o) { rep &= ~uint32(BITS_MASK); rep |= (o.rep & BITS_MASK); } uint32 rep; }; inline ConstraintScore makeScore(uint32 act = 0, uint32 lbd = 0) { ConstraintScore sc = {0}; sc.reset(act, lbd); return sc; } //! Type storing meta information about a constraint. class ConstraintInfo : private ConstraintScore { public: typedef ConstraintInfo Info; typedef ConstraintScore Score; ConstraintInfo(ConstraintType t = Constraint_t::Static) { static_assert(ConstraintScore::BITS_USED <= 28, "invalid score"); rep = uint32(t) << TYPE_SHIFT; } using ConstraintScore::lbd; using ConstraintScore::activity; ConstraintType type() const { return static_cast( (rep & uint32(TYPE_MASK)) >> TYPE_SHIFT ); } bool tagged() const { return test_bit(rep, TAG_BIT); } bool aux() const { return tagged() || test_bit(rep, AUX_BIT); } bool learnt() const { return type() != Constraint_t::Static; } const Score& score() const { return *this; } Score& score() { return *this; } Info& setType(ConstraintType t) { rep &= ~uint32(TYPE_MASK); rep |= (uint32(t) << TYPE_SHIFT); return *this; } Info& setScore(Score sc) { assign(sc); return *this; } Info& setActivity(uint32 a) { assign(makeScore(a, lbd())); return *this; } Info& setLbd(uint32 lbd) { assign(makeScore(activity(), lbd)); return *this; } Info& setTagged(bool b) { if (test_bit(rep, TAG_BIT) != b) store_toggle_bit(rep, TAG_BIT); return *this; } Info& setAux(bool b) { if (test_bit(rep, AUX_BIT) != b) store_toggle_bit(rep, AUX_BIT); return *this; } private: enum { TYPE_SHIFT = 28, AUX_BIT = 30, TAG_BIT = 31, TYPE_MASK = (3u << TYPE_SHIFT) }; }; //@} /** * \defgroup shared_con Shared * \brief %Constraint data that can safely be shared between solvers. * \ingroup constraint */ } #endif clingo-5.2.2/clasp/clasp/dependency_graph.h000066400000000000000000000453311320011352300206430ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_DEPENDENCY_GRAPH_H_INCLUDED #define CLASP_DEPENDENCY_GRAPH_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include namespace Clasp { class Solver; class SharedContext; struct SolverStats; //! Event type used to signal a (partial) check in disjunctive solving. struct SolveTestEvent : SolveEvent { SolveTestEvent(const Solver& s, uint32 hcc, bool partial); int result; //!< -1: before test, 0: unstable, 1: stable uint32 hcc :31;//!< hcc under test uint32 partial : 1;//!< partial test? uint64 confDelta; //!< conflicts before test uint64 choiceDelta;//!< choices before test double time; //!< time for test uint64 conflicts() const; uint64 choices() const; }; struct LoopReason_t { enum Type { Explicit = 0u, Implicit = 1u, }; }; typedef LoopReason_t::Type LoopType; namespace Asp { //! (Positive) Body-Atom-Dependency Graph. /*! * \ingroup shared_con * * Represents the PBADG of a logic program. Once initialized, the * PBDAG is static and read-only and thus can be shared between multiple solvers. * * \note Initialization is *not* thread-safe, i.e. must be done only once by one thread. */ class PrgDepGraph { public: enum NonHcfMapType { map_old = 0, map_new = 1 }; explicit PrgDepGraph(NonHcfMapType m = map_old); ~PrgDepGraph(); typedef uint32 NodeId; //! Type for storing a non head-cycle-free component of a disjunctive program. class NonHcfComponent { public: explicit NonHcfComponent(uint32 id, const PrgDepGraph& dep, SharedContext& generator, Configuration* c, uint32 scc, const VarVec& atoms, const VarVec& bodies); ~NonHcfComponent(); void assumptionsFromAssignment(const Solver& generator, LitVec& assumptionsOut) const; bool test(const Solver& generator, const LitVec& assumptions, VarVec& unfoundedOut) const; bool simplify(const Solver& generator) const; const SharedContext& ctx() const { return *prg_; } void update(const SharedContext& generator); uint32 id() const { return id_; } uint32 scc() const { return scc_; } private: friend class PrgDepGraph; NonHcfComponent(const NonHcfComponent&); NonHcfComponent& operator=(const NonHcfComponent&); class ComponentMap; const PrgDepGraph* dep_; SharedContext* prg_; ComponentMap* comp_; uint32 id_; uint32 scc_; }; //! A class for storing statistics on checking of non head-cycle-free components. class NonHcfStats { public: NonHcfStats(PrgDepGraph& g, uint32 level, bool inc); ~NonHcfStats(); void accept(StatsVisitor& out, bool final) const; void startStep(uint32 statsLevel); void endStep(); void addTo(StatsMap& problem, StatsMap& solving, StatsMap* accu) const; private: friend class PrgDepGraph; void addHcc(const NonHcfComponent&); void removeHcc(const NonHcfComponent&); NonHcfStats(const NonHcfStats&); NonHcfStats& operator=(const NonHcfStats&); struct Data; PrgDepGraph* graph_; Data* data_; }; typedef PodVector::type ComponentVec; typedef ComponentVec::const_iterator NonHcfIter; //! Base type for nodes. struct Node { Node(Literal l = Literal(0, false), uint32 sc = PrgNode::noScc) : lit(l), scc(sc), data(0), adj_(0), sep_(0) {} Literal lit; // literal of this node uint32 scc : 28;// scc of this node uint32 data : 4;// additional atom/body data NodeId* adj_; // list of adjacent nodes NodeId* sep_; // separates successor/predecessor nodes }; //! An atom node. /*! * The PBDAG stores a node of type AtomNode for each non-trivially connected atom. * The predecessors of an AtomNode are the bodies that define the atom. Its successors * are those bodies from the same SCC that contain the atom positively. */ struct AtomNode : public Node { enum Property { property_in_choice = 1u, property_in_disj = 2u, property_in_ext = 4u, property_in_non_hcf = 8u }; AtomNode() {} void set(Property p) { data |= (uint32)p; } void setProperties(uint32 f) { assert(f < 8); data |= f; } //! Contained in the head of a choice rule? bool inChoice() const { return (data & property_in_choice) != 0; } //! Contained in the head of a non-hcf disjunctive rule? bool inDisjunctive()const { return (data & property_in_disj) != 0; } //! Contained in an extended body? bool inExtended() const { return (data& property_in_ext) != 0; } //! Contained in a non-hcf SCC? bool inNonHcf() const { return (data & property_in_non_hcf) != 0; } //! Bodies (i.e. predecessors): bodies from other SCCs precede those from same SCC. const NodeId* bodies_begin() const { return adj_; } const NodeId* bodies_end() const { return sep_; } NodeId body(uint32 i) const { return bodies_begin()[i]; } //! Successors from same SCC [B1,...Bn, idMax]. /*! * \note If extended() is true, the atom is adjacent to some extended body. * In that case, the returned list looks like this: * [Bn1, ..., Bnj, idMax, Bext1, pos1, ..., Bextn, posn, idMax], where * each Bni is a normal body, each Bexti is an extended body and posi is the * position of this atom in Bexti. */ const NodeId* succs() const { return sep_; } //! Calls the given function object p once for each body containing this atom. template void visitSuccessors(const P& p) const { const NodeId* s = succs(); for (; *s != idMax; ++s) { p(*s); } if (inExtended()) { for (++s; *s != idMax; s += 2) { p(*s, *(s+1)); } } } }; enum { sentinel_atom = 0u }; //! A body node. /*! * The PBDAG stores a node of type BodyNode for each body that defines * a non-trivially connected atom. * The predecessors of a BodyNode are the body's subgoals. * Its successors are the heads that are defined by the body. * \note Normal bodies only store the positive subgoals from the same SCC, while * extended rule bodies store all subgoals. In the latter case, the positive subgoals from * the same SCC are stored as AtomNodes. All other subgoals are stored as literals. */ struct BodyNode : public Node { enum Flag { flag_has_bound = 1u, flag_has_weights = 2u, flag_has_delta = 4u, flag_seen = 8u }; explicit BodyNode(PrgBody* b, uint32 scc) : Node(b->literal(), scc) { if (scc == PrgNode::noScc || b->type() == Body_t::Normal) { data = 0; } else if (b->type() == Body_t::Count){ data = flag_has_bound; } else if (b->type() == Body_t::Sum) { data = flag_has_bound | flag_has_weights; } else { assert("UNKNOWN BODY TYPE!\n"); } } bool seen() const { return (data & flag_seen) != 0; } void seen(bool b) { if (b) data |= flag_seen; else data &= ~uint32(flag_seen); } //! Heads (i.e. successors): atoms from same SCC precede those from other SCCs. /*! * \note Disjunctive heads are stored in flattened atom-lists, where the * lists are terminated on both ends with the special sentinal atom 0. * E.g. given * x :- B. * y :- B. * a|b:- B. * a|c:- B. * would result in: [x,y,0,a,b,0,0,a,c,0] */ const NodeId* heads_begin() const { return adj_; } const NodeId* heads_end() const { return sep_ - extended(); } //! Any disjunctive heads? bool delta() const { return (data & flag_has_delta) != 0; } //! Predecessors from same SCC [a1,...an, idMax]. /*! * \note If extended() is true, the body stores all its subgoals and preds looks * like this: [a1, [w1], ..., aj, [wj], idMax, l1, [w1], ..., lk, [wk], idMax], where * each ai is an atom from the same SCC, each li is a literal of a subgoal from * other SCCs and wi is an optional weight (only for weight rules). */ const NodeId* preds() const { assert(scc != PrgNode::noScc); return sep_; } //! Returns idx of atomId in preds. uint32 get_pred_idx(NodeId atomId) const { const uint32 inc = pred_inc(); uint32 idx = 0; for (const NodeId* x = preds(); *x != idMax; x += inc, ++idx) { if (*x == atomId) return idx; } return idMax; } NodeId get_pred(uint32 idx) const { return *(preds() + (idx*pred_inc())); } //! Increment to jump from one pred to the next. uint32 pred_inc() const { return 1 + sum(); } //! Weight of ith subgoal. /*! * \pre i in [0, num_preds()) */ uint32 pred_weight(uint32 i, bool ext) const { return !sum() ? 1 : *(preds() + (i*pred_inc()) + (1+uint32(ext))); } //! Number of predecessors (counting external subgoals). uint32 num_preds() const { if (scc == PrgNode::noScc) return 0; uint32 p = 0; const NodeId* x = preds(); const uint32 inc = pred_inc(); for (; *x != idMax; x += inc) { ++p; } x += extended(); for (; *x != idMax; x += inc) { ++p; } return p; } //! Is the body an extended body? bool extended()const { return (data & flag_has_bound) != 0u; } //! Is the body a sum body? bool sum() const { return (data & flag_has_weights) != 0u; } //! Bound of extended body. weight_t ext_bound() const { return sep_[-1]; } }; //! Adds SCCs to the graph. /*! * \param prg The logic program for which the dependency graph is to be created. * \param sccAtoms Atoms of the logic program that are strongly connected. * \param nonHcfs Sorted list of non-hcf sccs */ void addSccs(LogicProgram& prg, const AtomList& sccAtoms, const NonHcfSet& nonHcfs); //! Removes inactive non-hcfs. void simplify(const Solver& s); //! Number of atoms in graph. uint32 numAtoms() const { return (uint32)atoms_.size(); } //! Number of bodies in graph. uint32 numBodies()const { return (uint32)bodies_.size(); } //! Sum of atoms and bodies. uint32 nodes() const { return numAtoms()+numBodies(); } //! Returns AtomNode of atom with given id. const AtomNode& getAtom(NodeId atomId) const { assert(atomId < atoms_.size()); return atoms_[atomId]; } NodeId id(const AtomNode& n) const { return static_cast(&n - &atoms_[0]); } //! Returns BodyNode of body with given id. const BodyNode& getBody(NodeId bodyId) const { assert(bodyId < bodies_.size()); return bodies_[bodyId]; } //! Calls the given function object p once for each body-literal. template void visitBodyLiterals(const BodyNode& n, const P& p) const { const NodeId* x = n.preds(); const uint32 inc = n.pred_inc(); uint32 i = 0; for (; *x != idMax; x += inc, ++i) { p(getAtom(*x).lit, i, false); } x += n.extended(); for (; *x != idMax; x += inc, ++i) { p(Literal::fromRep(*x), i, true); } } NonHcfIter nonHcfBegin() const { return components_.begin(); } NonHcfIter nonHcfEnd() const { return components_.end(); } uint32 numNonHcfs() const { return (uint32)components_.size(); } NonHcfStats* nonHcfStats() const { return stats_; } NonHcfStats* enableNonHcfStats(uint32 level, bool incremental); private: typedef PodVector::type AtomVec; typedef PodVector::type BodyVec; PrgDepGraph(const PrgDepGraph&); PrgDepGraph& operator=(const PrgDepGraph&); inline bool relevantPrgAtom(const Solver& s, PrgAtom* a) const; inline bool relevantPrgBody(const Solver& s, PrgBody* b) const; NonHcfMapType nonHcfMapType() const { return static_cast(mapType_); } NodeId createBody(PrgBody* b, uint32 bScc); NodeId createAtom(Literal lit, uint32 aScc); NodeId addBody(const LogicProgram& prg, PrgBody*); NodeId addDisj(const LogicProgram& prg, PrgDisj*); uint32 addHeads(const LogicProgram& prg, PrgBody*, VarVec& atoms) const; uint32 getAtoms(const LogicProgram& prg, PrgDisj*, VarVec& atoms) const; void addPreds(const LogicProgram& prg, PrgBody*, uint32 bScc, VarVec& preds) const; void initBody(uint32 id, const VarVec& preds, const VarVec& atHeads); void initAtom(uint32 id, uint32 prop, const VarVec& adj, uint32 preds); void addNonHcf(uint32 id, SharedContext& ctx, Configuration* c, uint32 scc); AtomVec atoms_; BodyVec bodies_; ComponentVec components_; NonHcfStats* stats_; uint32 seenComponents_ : 31; uint32 mapType_ : 1; }; } // namespace Asp //! External dependency graph. /*! * \ingroup shared_con * * Represents external dependencies explicitly given by the user. * For example, via aspif edge directives or the graph block in extended dimacs format. * \note Initialization is *not* thread-safe, i.e. must be done only once by one thread. */ class ExtDepGraph { public: struct Arc { Literal lit; uint32 node[2]; uint32 tail() const { return node[0]; } uint32 head() const { return node[1]; } static Arc create(Literal x, uint32 nodeX, uint32 nodeY) { Arc a = {x, {nodeX, nodeY}}; return a; } }; struct Inv { uint32 tail() const { return rep >> 1; } Literal lit; uint32 rep; }; template struct CmpArc { bool operator()(const Arc& lhs, uint32 n) const { return lhs.node[x] < n; } bool operator()(uint32 n, const Arc& rhs) const { return n < rhs.node[x]; } bool operator()(const Arc& lhs, const Arc& rhs) const { return lhs.node[x] < rhs.node[x] || (lhs.node[x] == rhs.node[x] && lhs.node[1-x] < rhs.node[1-x]); } }; explicit ExtDepGraph(uint32 numNodeGuess = 0); ~ExtDepGraph(); void addEdge(Literal lit, uint32 startNode, uint32 endNode); void update(); uint32 finalize(SharedContext& ctx); bool frozen() const; uint64 attach(Solver& s, Constraint& p, uint64 genId); void detach(Solver* s, Constraint& p); const Arc& arc(uint32 id) const { return fwdArcs_[id]; } const Arc* fwdBegin(uint32 n) const { uint32 X = nodes_[n].fwdOff; return validOff(X) ? &fwdArcs_[X] : 0; } const Arc* fwdNext(const Arc* a)const { assert(a); return a[0].node[0] == a[1].node[0] ? ++a : 0; } const Inv* invBegin(uint32 n) const { uint32 X = nodes_[n].invOff; return validOff(X) ? &invArcs_[X] : 0; } const Inv* invNext(const Inv* a)const { assert(a); return (a->rep & 1u) == 1u ? ++a : 0; } uint32 nodes() const { return maxNode_; } uint32 edges() const { return comEdge_; } bool validNode(uint32 n) const { return n < maxNode_; } private: ExtDepGraph(const ExtDepGraph&); ExtDepGraph& operator=(const ExtDepGraph&); struct Node { uint32 fwdOff; uint32 invOff; }; typedef PodVector::type ArcVec; typedef PodVector::type InvVec; typedef PodVector::type NodeVec; bool validOff(uint32 n) const { return n != UINT32_MAX; } ArcVec fwdArcs_; // arcs ordered by node id InvVec invArcs_; // inverse arcs ordered by node id NodeVec nodes_; // data for the nodes of this graph uint32 maxNode_; // nodes have ids in the range [0, maxNode_) uint32 comEdge_; // number of edges committed uint32 genCnt_; // generation count (for incremental updates) }; //! Acyclicity checker that operates on a ExtDepGraph. /*! * \ingroup propagator * \see M. Gebser, T. Janhunen, and J. Rintanen: "SAT Modulo Graphs: Acyclicity" */ class AcyclicityCheck : public PostPropagator { public: enum Strategy { prop_full = 0, // forward and backward check with clause generation prop_full_imp = 1, // forward and backward check without clause generation prop_fwd = 2, // only forward check }; enum { PRIO = PostPropagator::priority_reserved_ufs + 1 }; typedef ExtDepGraph DependencyGraph; explicit AcyclicityCheck(DependencyGraph* graph); ~AcyclicityCheck(); void setStrategy(Strategy p); void setStrategy(const SolverParams& opts); // base interface uint32 priority() const { return uint32(PRIO); } bool init(Solver&); void reset(); bool propagateFixpoint(Solver& s, PostPropagator* ctx); bool isModel(Solver& s); bool valid(Solver& s); void destroy(Solver* s, bool detach); private: AcyclicityCheck(const AcyclicityCheck&); AcyclicityCheck& operator=(const AcyclicityCheck&); struct Parent { static Parent create(Literal x, uint32 n) { Parent p = {x, n}; return p; } Literal lit; uint32 node; }; enum { config_bit = 2 }; struct ReasonStore; typedef DependencyGraph::Arc Arc; typedef DependencyGraph::Inv Inv; typedef PodQueue EdgeQueue; typedef PodVector::type TagVec; typedef PodVector::type ParentVec; bool dfsForward(Solver& s, const Arc& e); bool dfsBackward(Solver& s, const Arc& e); void setParent(Var node, const Parent& p){ parent_[node] = p; } void pushVisit(Var node, uint32 tv) { nStack_.push_back(node); tags_[node] = tv; } bool visited(Var node, uint32 tv) const { return tags_[node] == tv; } uint32 startSearch(); void addClauseLit(Solver& s, Literal p); void setReason(Literal p, LitVec::const_iterator first, LitVec::const_iterator end); // ------------------------------------------------------------------------------------------- // constraint interface PropResult propagate(Solver&, Literal, uint32& eId) { todo_.push(graph_->arc(eId)); return PropResult(true, true); } void reason(Solver& s, Literal, LitVec&); Strategy strategy() const { return static_cast(strat_ & 3u); } DependencyGraph* graph_; // my graph Solver* solver_; // my solver ReasonStore* nogoods_;// stores at most one reason per literal uint32 strat_; // active propagation strategy uint32 tagCnt_; // generation counter for searches EdgeQueue todo_; // edges that recently became enabled TagVec tags_; // tag for each node ParentVec parent_; // parents for each node VarVec nStack_; // node stack for df-search LitVec reason_; // reason for conflict/implication uint64 genId_; // generation identifier }; } #endif clingo-5.2.2/clasp/clasp/enumerator.h000066400000000000000000000343641320011352300175310ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_ENUMERATOR_H_INCLUDED #define CLASP_ENUMERATOR_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include namespace Clasp { class Solver; class SharedContext; class Enumerator; class EnumerationConstraint; //! Type for storing a model. struct Model { enum Type { Sat = 0u, Brave = 1u, Cautious = 2u, User = 4u }; enum { cons_mask = 3u, est_pos_mask= 4u, est_neg_mask = 8u }; static uint8 estMask(Literal p) { return est_pos_mask << ((int)p.sign()); } bool hasVar(Var v) const { return values && v < values->size(); } //! True if this model stores current (cautious/brave) consequences. bool consequences() const { return (type & cons_mask) != 0; } //! For sat models, value of v in model. Otherwise, undefined. ValueRep value(Var v) const { assert(hasVar(v)); return (*values)[v] & 3u; } //! True if p is true in model or part of current consequences. bool isTrue(Literal p) const { return (value(p.var()) & trueValue(p)) != 0; } //! True if p is part of a definite answer. bool isDef(Literal p) const { return isTrue(p) && (def || ((type & Cautious) == 0u) || !isEst(p)); } //! True if p is part of the current estimate of consequences. bool isEst(Literal p) const { assert(hasVar(p.var())); return ((*values)[p.var()] & estMask(p)) != 0; } void reset(); uint64 num; // running number of this model const Enumerator* ctx; // ctx in which model was found const ValueVec* values; // variable assignment or consequences const SumVec* costs; // associated costs (or 0) uint32 sId :16;// id of solver that found the model uint32 type:12;// type of model uint32 opt : 1;// whether the model is optimal w.r.t costs (0: unknown) uint32 def : 1;// whether the model is definite w.r.t consequences (0: unknown) uint32 sym : 1;// whether symmetric models are possible uint32 up : 1;// whether the model was updated on last unsat }; /** * \defgroup enumerator Solving * \brief Enumerators and solve algorithms. */ //@{ //! Options for configuring enumeration. struct EnumOptions { typedef MinimizeMode OptMode; typedef ProjectMode ProjMode; enum EnumType { enum_auto = 0, enum_bt = 1, enum_record = 2, enum_dom_record = 3, enum_consequences = 4, enum_brave = 5, enum_cautious = 6, enum_query = 7, enum_user = 8 }; EnumOptions() : numModels(-1), enumMode(enum_auto), optMode(MinimizeMode_t::optimize), proMode(ProjectMode_t::Implicit), project(0) {} static Enumerator* createModelEnumerator(const EnumOptions& opts); static Enumerator* createConsEnumerator(const EnumOptions& opts); static Enumerator* nullEnumerator(); static Enumerator* createEnumerator(const EnumOptions& opts); bool consequences() const { return (enumMode & enum_consequences) != 0; } bool models() const { return (enumMode < enum_consequences); } bool optimize() const { return ((optMode & MinimizeMode_t::optimize) != 0); } int64 numModels; /*!< Number of models to compute. */ EnumType enumMode; /*!< Enumeration type to use. */ OptMode optMode; /*!< Optimization mode to use. */ ProjMode proMode; /*!< Projection mode to use. */ uint32 project; /*!< Options for projection. */ SumVec optBound; /*!< Initial bound for optimize statements. */ }; const char* modelType(const Model& m); //! Interface for supporting enumeration of models. /*! * Enumerators are global w.r.t a solve algorithm. That is, * even if the solve algorithm itself uses a parallel search, there * shall be only one enumerator and it is the user's responsibility * to protect the enumerator with appropriate locking. * * Concrete enumerators must implement a function for preparing a problem for enumeration * and an EnumerationConstraint to be added to each solver attached to the problem. * It is then the job of the actual solve algorithm to commit models to the enumerator * and to integrate new information into attached solvers via appropriate calls to * Enumerator::update(). */ class Enumerator { public: typedef EnumerationConstraint* ConPtr; typedef EnumerationConstraint& ConRef; typedef const SharedMinimizeData* Minimizer; typedef EnumOptions::OptMode OptMode; class ThreadQueue; explicit Enumerator(); virtual ~Enumerator(); void reset(); //! Prepares the problem for enumeration. /*! * The function shall be called once before search is started and before SharedContext::endInit() * was called. It freezes enumeration-related variables and adds a suitable enumeration constraint * to the master solver. * * \pre The problem is not yet frozen, i.e. SharedContext::endInit() was not yet called. * \param problem The problem on which this enumerator should work. * \param opt Minimization mode to apply during enumeration. * \param limit Optional hint on max number of models to compute. * * \note In the incremental setting, init() must be called once for each incremental step. */ int init(SharedContext& problem, OptMode opt = MinimizeMode_t::optimize, int limit = 0); //! Prepares the given solver for enumeration under the given path. /*! * The function shall be called once before solving is started. It pushes the * given path to the solver by calling Solver::pushRoot() and prepares s for * enumeration/optimization. * \return true if path was added. */ bool start(Solver& s, const LitVec& path = LitVec(), bool disjointPath = false) const; //! Updates the given solver with enumeration-related information. /*! * The function is used to integrate enumeration-related information, * like minimization bounds or previously committed models, into the search space of s. * It shall be called after each commit. * * \param s The solver to update. * \note The function is concurrency-safe, i.e. can be called * concurrently by different solvers. */ bool update(Solver& s) const; /*! * \name Commit functions * Functions for committing enumeration-related information to the enumerator. * \note The functions in this group are *not* concurrency-safe, i.e. in a parallel search * at most one solver shall call a commit function at any one time. */ //@{ //! Commits the model stored in the given solver. /*! * If the model is valid and unique, the function returns true and the * model can be accessed via a call to Enumerator::lastModel(). * Otherwise, the function returns false. * In either case, Enumerator::update(s) shall be called * in order to continue search for further models. * * \pre The solver's assignment is total. */ bool commitModel(Solver& s); //! Expands the next symmetric model if any. bool commitSymmetric(Solver& s); //! Commits an unsatisfiable path stored in the given solver. /*! * The return value determines how search should proceed. * If true is returned, the enumerator has relaxed an enumeration constraint * and search may continue after a call to Enumerator::update(s). * Otherwise, the search shall be stopped. */ bool commitUnsat(Solver& s); //! Commits the given clause to this enumerator. bool commitClause(const LitVec& clause) const; //! Marks current enumeration phase as completed. /*! * If the enumerator was initialized with a minimization constraint and * optimization mode MinimizeMode_t::enumOpt, the optimal bound is committed, * the enumerator is prepared for enumerating optimal models, and the function * returns false. Otherwise, the function returns true and search shall be stopped. */ bool commitComplete(); //! Commits the state stored in the given solver. /*! * Calls commitModel() or commitUnsat() depending on the state of s. * The function returns value_true, to signal that s stores a valid and * unique model, value_false to signal that search shall be stopped, and * value_free otherwise. * \see commitModel() * \see commitUnsat() */ uint8 commit(Solver& s); //@} //! Removes from s the path that was passed to start() and any active (minimization) bound. void end(Solver& s) const; //! Returns the number of models enumerated so far. uint64 enumerated() const { return model_.num; } //! Returns the last model enumerated. /*! * \note If enumerated() is equal to 0, the returned object is in an indeterminate state. */ const Model& lastModel() const { return model_; } //! Returns whether optimization is active. bool optimize() const { return mini_ && mini_->mode() != MinimizeMode_t::enumerate && model_.opt == 0; } //! Returns whether computed models are still tentative. bool tentative() const { return mini_ && mini_->mode() == MinimizeMode_t::enumOpt && model_.opt == 0; } //! Returns the active minimization constraint if any. Minimizer minimizer() const { return mini_; } //! Returns the type of models this enumerator computes. virtual int modelType() const { return Model::Sat; } enum UnsatType { unsat_stop = 0u, /*!< First unsat stops search - commitUnsat() always return false. */ unsat_cont = 1u, /*!< Unsat may be tentative - commitUnsat() may return true. */ unsat_sync = 3u, /*!< Similar to unsat_cont but additionally requires synchronization among threads. */ }; //! Returns whether unsat may be tentative and/or requires synchronization. virtual int unsatType() const; //! Returns whether or not this enumerator supports full restarts once a model was found. virtual bool supportsRestarts() const { return true; } //! Returns whether or not this enumerator supports parallel search. virtual bool supportsParallel() const { return true; } //! Returns whether or not this enumerator supports splitting-based search. virtual bool supportsSplitting(const SharedContext& problem) const; //! Returns whether this enumerator requires exhaustive search to produce a definite answer. virtual bool exhaustive() const { return mini_ && mini_->mode() != MinimizeMode_t::enumerate; } //! Sets whether the search path stored in s is disjoint from all others. void setDisjoint(Solver& s, bool b) const; //! Sets whether symmetric should be ignored. void setIgnoreSymmetric(bool b); ConPtr constraint(const Solver& s) const; protected: //! Shall prepare the enumerator and freeze any enumeration-related variable. /*! * \return A prototypical enumeration constraint to be used in a solver. */ virtual ConPtr doInit(SharedContext& ctx, SharedMinimizeData* min, int numModels) = 0; virtual void doReset(); Model& model(); private: class SharedQueue; Enumerator(const Enumerator&); Enumerator& operator=(const Enumerator&); ConRef constraintRef(const Solver& s) const; SharedMinimizeData* mini_; SharedQueue* queue_; SumVec costs_; Model model_; }; //! A solver-local (i.e. thread-local) constraint to support enumeration. /*! * An enumeration constraint is used to extract/store enumeration-related information * from models. */ class EnumerationConstraint : public Constraint { public: typedef EnumerationConstraint* ConPtr; typedef MinimizeConstraint* MinPtr; typedef Enumerator::ThreadQueue* QueuePtr; //! Returns true if search-path is disjoint from all others. bool disjointPath()const { return disjoint_; } ValueRep state() const { return state_; } ValueRep resetMode() const { return upMode_; } //! Returns true if optimization is active. bool optimize() const; MinPtr minimizer() const { return mini_; } // Methods used by enumerator void init(Solver& s, SharedMinimizeData* min, QueuePtr q); bool start(Solver& s, const LitVec& path, bool disjoint); void end(Solver& s); bool update(Solver& s); void setDisjoint(bool x); bool integrateBound(Solver& s); bool integrateNogoods(Solver& s); bool commitModel(Enumerator& ctx, Solver& s); bool commitUnsat(Enumerator& ctx, Solver& s); void setMinimizer(MinPtr min) { mini_ = min; } void add(Constraint* c); void modelHeuristic(Solver& s); protected: EnumerationConstraint(); virtual ~EnumerationConstraint(); // base interface virtual void destroy(Solver* s, bool detach); virtual PropResult propagate(Solver&, Literal, uint32&) { return PropResult(true, true); } virtual void reason(Solver&, Literal, LitVec&) {} virtual bool simplify(Solver& s, bool reinit); virtual bool valid(Solver& s); virtual Constraint* cloneAttach(Solver& s); // own interface virtual ConPtr clone() = 0; virtual bool doUpdate(Solver& s) = 0; virtual void doCommitModel(Enumerator&, Solver&) {} virtual void doCommitUnsat(Enumerator&, Solver&) {} uint32 rootLevel() const { return root_; } private: typedef PodVector::type ConstraintDB; typedef SingleOwnerPtr QPtr; MinimizeConstraint* mini_; QPtr queue_; ConstraintDB nogoods_; LitVec next_; uint32 root_; ValueRep state_; ValueRep upMode_; ValueRep heuristic_; bool disjoint_; }; //@} } #endif clingo-5.2.2/clasp/clasp/heuristics.h000066400000000000000000000407341320011352300175300ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_HEURISTICS_H_INCLUDED #define CLASP_HEURISTICS_H_INCLUDED #ifdef _MSC_VER #pragma once #endif /*! * \file * \brief Defines various decision heuristics to be used in clasp. */ #include #include #include #include namespace Clasp { //! Computes a moms-like score for var v. uint32 momsScore(const Solver& s, Var v); //! A variant of the BerkMin decision heuristic from the BerkMin Sat-Solver. /*! * \ingroup heuristic * \see E. Goldberg, Y. Navikov: "BerkMin: a Fast and Robust Sat-Solver" * * \note * This version of the BerkMin heuristic varies mostly in the following points from the original BerkMin: * -# it considers loop-nogoods if requested (this is the default) * -# it uses a MOMS-like heuristic as long as there are no conflicts (and therefore no activities) * -# it uses a MOMS-like score to break ties whenever multiple variables from an unsatisfied learnt constraint have equal activities * -# it uses a lazy decaying scheme that only touches active variables */ class ClaspBerkmin : public DecisionHeuristic { public: /*! * \note Checks at most params.param candidates when searching for not yet * satisfied learnt constraints. If param is 0, all candidates are checked. */ explicit ClaspBerkmin(const HeuParams& params = HeuParams()); void setConfig(const HeuParams& params); void startInit(const Solver& s); void endInit(Solver& s); void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t); void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit); bool bump(const Solver& s, const WeightLitVec& lits, double adj); void undoUntil(const Solver&, LitVec::size_type); void updateVar(const Solver& s, Var v, uint32 n); protected: Literal doSelect(Solver& s); private: Literal selectLiteral(Solver& s, Var v, bool vsids) const; Literal selectRange(Solver& s, const Literal* first, const Literal* last); bool initHuang() const { return order_.score[0].occ == 1; } void initHuang(bool b) { order_.score[0].occ = b; } bool hasActivities() const { return order_.score[0].act != 0; } void hasActivities(bool b) { order_.score[0].act = b; } Var getMostActiveFreeVar(const Solver& s); Var getTopMoms(const Solver& s); bool hasTopUnsat(Solver& s); // Gathers heuristic information for one variable v. struct HScore { HScore(uint32 d = 0) : occ(0), act(0), dec(uint16(d)) {} void incAct(uint32 gd, bool h, bool sign) { occ += int(h) * (1 - (2*int(sign))); decay(gd, h); ++act; } void incOcc(bool sign) { occ += 1 - (2*int(sign)); } uint32 decay(uint32 gd, bool h) { if (uint32 x = (gd-dec)) { // NOTE: shifts might overflow, i.e. // activity is actually shifted by x%32. // We deliberately ignore this "logical inaccuracy" // and treat it as random noise ;) act >>= x; dec = uint16(gd); occ /= (1<<(x*int(h))); } return act; } int32 occ; uint16 act; uint16 dec; }; typedef PodVector::type Scores; typedef VarVec::iterator Pos; struct Order { explicit Order() : decay(0), huang(false), resScore(3u) {} struct Compare { explicit Compare(Order* o) : self(o) {} bool operator()(Var v1, Var v2) const { return self->decayedScore(v1) > self->decayedScore(v2) || (self->score[v1].act == self->score[v2].act && v1 < v2); } Order* self; }; uint32 decayedScore(Var v) { return score[v].decay(decay, huang); } int32 occ(Var v) const { return score[v].occ; } void inc(Literal p, bool inNant) { if (!this->nant || inNant) { score[p.var()].incAct(decay, huang, p.sign()); } } void incOcc(Literal p) { score[p.var()].incOcc(p.sign()); } int compare(Var v1, Var v2) { return int(decayedScore(v1)) - int(decayedScore(v2)); } void resetDecay(); Scores score; // For each var v score_[v] stores heuristic score of v uint32 decay; // "global" decay counter. Increased every decP_ decisions bool huang; // Use Huang's scoring scheme (see: Jinbo Huang: "A Case for Simple SAT Solvers") bool nant; // only score vars v with varInfo(v).nant()? uint8 resScore; private: Order(const Order&); Order& operator=(const Order&); } order_; VarVec cache_; // Caches the most active variables LitVec freeLits_; // Stores free variables of the last learnt conflict clause that is not sat LitVec freeOtherLits_; // Stores free variables of the last other learnt nogood that is not sat uint32 topConflict_; // Index into the array of learnt nogoods used when searching for conflict clauses that are not sat uint32 topOther_; // Index into the array of learnt nogoods used when searching for other learnt nogoods that are not sat Var front_; // First variable whose truth-value is not already known - reset on backtracking Pos cacheFront_; // First unprocessed cache position - reset on backtracking uint32 cacheSize_; // Cache at most cacheSize_ variables uint32 numVsids_; // Number of consecutive vsids-based decisions uint32 maxBerkmin_; // When searching for an open learnt constraint, check at most maxBerkmin_ candidates. TypeSet types_; // When searching for an open learnt constraint, consider these types of nogoods. RNG rng_; }; //! Variable Move To Front decision strategies inspired by Siege. /*! * \ingroup heuristic * \see Lawrence Ryan: "Efficient Algorithms for Clause Learning SAT-Solvers" * * \note This implementation of VMTF differs from the original implementation in three points: * - it optionally moves to the front a selection of variables from learnt loop nogoods * - it measures variable activity by using a BerkMin-like score scheme * - the initial order of the var list is determined using a MOMs-like score scheme */ class ClaspVmtf : public DecisionHeuristic { public: /*! * \note Moves at most params.param literals from constraints used during * conflict resolution to the front. If params.param is 0, the default is * to move up to 8 literals. */ explicit ClaspVmtf(const HeuParams& params = HeuParams()); void setConfig(const HeuParams& params); void startInit(const Solver& s); void endInit(Solver&); void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t); void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit); bool bump(const Solver& s, const WeightLitVec& lits, double adj); void simplify(const Solver&, LitVec::size_type); void undoUntil(const Solver&, LitVec::size_type); void updateVar(const Solver& s, Var v, uint32 n); protected: Literal doSelect(Solver& s); private: Literal selectRange(Solver& s, const Literal* first, const Literal* last); typedef std::list VarList; typedef VarList::iterator VarPos; struct VarInfo { VarInfo(VarPos it) : pos_(it), activity_(0), occ_(0), decay_(0) { } VarPos pos_; // position of var in var list uint32 activity_; // activity of var - initially 0 int32 occ_; // which literal of var occurred more often in learnt constraints? uint32 decay_; // counter for lazy decaying activity uint32& activity(uint32 globalDecay) { if (uint32 x = (globalDecay - decay_)) { activity_ >>= (x<<1); decay_ = globalDecay; } return activity_; } }; typedef PodVector::type Score; struct LessLevel { LessLevel(const Solver& s, const Score& sc) : s_(s), sc_(sc) {} bool operator()(Var v1, Var v2) const { return s_.level(v1) < s_.level(v2) || (s_.level(v1) == s_.level(v2) && sc_[v1].activity_ > sc_[v2].activity_); } bool operator()(Literal l1, Literal l2) const { return (*this)(l1.var(), l2.var()); } private: LessLevel& operator=(const LessLevel&); const Solver& s_; const Score& sc_; }; Score score_; // For each var v score_[v] stores heuristic score of v VarList vars_; // List of possible choices, initially ordered by MOMs-like score VarVec mtf_; // Vars to be moved to the front of vars_ VarPos front_; // Current front-position in var list - reset on backtracking uint32 decay_; // "Global" decay counter. Increased every 512 decisions uint32 nMove_; // Limit on number of vars to move TypeSet types_; // Type of nogoods to score during resolution uint32 scType_;// Type of scoring bool nant_; // only move vars v with varInfo(v).nant()? }; //! Score type for VSIDS heuristic. /*! * \see ClaspVsids */ struct VsidsScore { typedef VsidsScore SC; VsidsScore(double sc = 0.0) : value(sc) {} double get() const { return value; } bool operator>(const SC& o) const { return value > o.value; } void set(double f) { value = f; } template static double applyFactor(C&, Var, double f) { return f; } double value; // activity }; //! A variable state independent decision heuristic favoring variables that were active in recent conflicts. /*! * \ingroup heuristic * \see M. W. Moskewicz, C. F. Madigan, Y. Zhao, L. Zhang, and S. Malik: * "Chaff: Engineering an Efficient SAT Solver" * * \note By default, the implementation uses the exponential VSIDS scheme from MiniSAT and * applies a MOMs-like score scheme to get an initial var order. */ template class ClaspVsids_t : public DecisionHeuristic { public: /*! * \note Uses params.param to init the decay value d and inc factor 1.0/d. * If params.param is 0, d is set 0.95. Otherwise, d is set to 0.x, where x is params.param. */ explicit ClaspVsids_t(const HeuParams& params = HeuParams()); virtual void setConfig(const HeuParams& params); virtual void startInit(const Solver& s); virtual void endInit(Solver&); virtual void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t); virtual void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit); virtual bool bump(const Solver& s, const WeightLitVec& lits, double adj); virtual void undoUntil(const Solver&, LitVec::size_type); virtual void simplify(const Solver&, LitVec::size_type); virtual void updateVar(const Solver& s, Var v, uint32 n); protected: virtual Literal doSelect(Solver& s); virtual Literal selectRange(Solver& s, const Literal* first, const Literal* last); virtual void initScores(Solver& s, bool moms); typedef typename PodVector::type ScoreVec; typedef PodVector::type OccVec; void updateVarActivity(const Solver& s, Var v, double f = 1.0); void incOcc(Literal p) { occ_[p.var()] += 1 - (int(p.sign()) << 1); } int occ(Var v) const { return occ_[v]; } void normalize(); struct CmpScore { explicit CmpScore(const ScoreVec& s) : sc_(s) {} bool operator()(Var v1, Var v2) const { return sc_[v1] > sc_[v2]; } private: CmpScore& operator=(const CmpScore&); const ScoreVec& sc_; }; typedef bk_lib::indexed_priority_queue VarOrder; struct Decay : Range{ Decay(double x = 0.0, double y = 0.95, uint32 b = 0, uint32 f = 0) : Range(x, y), bump(b), freq(f), next(f) { this->df = 1.0 / (freq && lo > 0.0 ? lo : hi); } double df; // active decay factor for evsids (>= 1.0) uint32 bump; uint32 freq : 16; uint32 next : 16; }; ScoreVec score_; // vsids score for each variable OccVec occ_; // occurrence balance of each variable VarOrder vars_; // priority heap of variables Decay decay_; // (dynamic) decaying strategy double inc_; // var bump for evsids or conflict index for acids (increased on conflict) TypeSet types_; // set of constraints to score uint32 scType_;// score type (one of HeuParams::Score) bool acids_; // whether to use acids instead if evsids scoring bool nant_; // whether bumps are restricted to vars v with varInfo(v).nant() }; typedef ClaspVsids_t ClaspVsids; //! Score type for DomainHeuristic. /*! * \see DomainHeuristic */ struct DomScore : VsidsScore { static const uint32 domMax = (1u << 30) - 1; typedef DomScore SC; DomScore(double v = 0.0) : VsidsScore(v), level(0), factor(1), domP(domMax), sign(0), init(0) {} bool operator>(const SC& o) const { return (level > o.level) || (level == o.level && value > o.value); } bool isDom() const { return domP != domMax; } void setDom(uint32 key) { domP = key; } template static double applyFactor(C& sc, Var v, double f) { int16 df = sc[v].factor; return df == 1 ? f : static_cast(df) * f; } int16 level; // priority level int16 factor; // factor used when bumping activity uint32 domP : 30; // index into dom-table if dom var uint32 sign : 1; // whether v has a sign modification uint32 init : 1; // whether value is from init modification }; //! A VSIDS heuristic supporting additional domain knowledge. /*! * \ingroup heuristic * * \see M. Gebser, B. Kaufmann, R. Otero, J. Romero, T. Schaub, P. Wanko: * "Domain-specific Heuristics in Answer Set Programming", * http://www.cs.uni-potsdam.de/wv/pdfformat/gekaotroscwa13a.pdf */ class DomainHeuristic : public ClaspVsids_t , private Constraint { public: typedef ClaspVsids_t BaseType; explicit DomainHeuristic(const HeuParams& params = HeuParams()); ~DomainHeuristic(); void setDefaultMod(HeuParams::DomMod mod, uint32 prefSet); virtual void setConfig(const HeuParams& params); virtual void startInit(const Solver& s); const DomScore& score(Var v) const { return score_[v]; } protected: // base interface virtual Literal doSelect(Solver& s); virtual void initScores(Solver& s, bool moms); virtual void detach(Solver& s); // Constraint interface virtual Constraint* cloneAttach(Solver&) { return 0; } virtual void reason(Solver&, Literal, LitVec&){} virtual PropResult propagate(Solver&, Literal, uint32&); virtual void undoLevel(Solver& s); private: struct DomAction { static const uint32 UNDO_NIL = (1u << 31) - 1; uint32 var:30; // dom var to be modified uint32 mod: 2; // modification to apply uint32 undo:31;// next action in undo list uint32 next: 1;// next action belongs to same condition? int16 bias; // value to apply uint16 prio; // prio of modification }; struct DomPrio { void clear() { prio[0] = prio[1] = prio[2] = prio[3] = 0; } uint16 operator[](unsigned i) const { return prio[i]; } uint16& operator[](unsigned i) { return prio[i]; } uint16 prio[4]; }; struct Frame { Frame(uint32 lev, uint32 h) : dl(lev), head(h) {} uint32 dl; uint32 head; }; typedef PodVector::type ActionVec; typedef PodVector::type PrioVec; typedef PodVector::type FrameVec; typedef DomainTable::ValueType DomMod; typedef PodVector >::type VarScoreVec; uint32 addDomAction(const DomMod& e, Solver& s, VarScoreVec& outInit, Literal& lastW); void addDefAction(Solver& s, Literal x, int16 lev, uint32 domKey); void pushUndo(uint32& head, uint32 actionId); void applyAction(Solver& s, DomAction& act, uint16& oldPrio); uint16& prio(Var v, uint32 mod) { return prios_[score_[v].domP][mod]; } PrioVec prios_; // priorities for domain vars ActionVec actions_; // dynamic modifications FrameVec frames_; // dynamic undo information uint32 domSeen_; // offset into domain table uint32 defMax_; // max var with default modification uint16 defMod_; // default modifier uint16 defPref_; // default preferences }; } #endif clingo-5.2.2/clasp/clasp/literal.h000066400000000000000000000217401320011352300167760ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_LITERAL_H_INCLUDED #define CLASP_LITERAL_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include // std::swap #include /*! * \file * \brief Types and functions related to literals and variables. */ namespace Clasp { /*! * \addtogroup constraint */ //@{ //! A variable is an integer in the range [0..varMax). typedef uint32 Var; //! varMax is not a valid variale, i.e. currently Clasp supports at most 2^30 variables. const Var varMax = (Var(1) << 30); //! The variable 0 has a special meaning in the solver. const Var sentVar = 0; //! Literal ids are in the range [0..litIdMax). const uint32 litIdMax = (Var(1) << 31); //! Possible types of a variable. struct Var_t { enum Type { Atom = 1, Body = 2, Hybrid = Atom | Body}; static bool isBody(Type t) { return (static_cast(t) & static_cast(Body)) != 0; } static bool isAtom(Type t) { return (static_cast(t) & static_cast(Atom)) != 0; } }; typedef Var_t::Type VarType; //! A literal is a variable or its negation. /*! * \par Implementation: * A literal's state is stored in a single 32-bit integer as follows: * - 30-bits : variable id * - 1-bit : sign, 1 if negative, 0 if positive * - 1-bit : general purpose flag for marking a literal instance */ class Literal { public: static const uint32 sign_bit = 2u; static const uint32 flag_bit = 1u; //! The default constructor creates the positive literal of the special sentinel var. Literal() : rep_(0) { } //! Creates a literal of the variable var with sign s. /*! * \param var The literal's variable. * \param sign true if new literal should be negative. * \pre var < varMax */ Literal(Var var, bool sign) : rep_( (var<> sign_bit; } //! Returns the sign of the literal. /*! * \return true if the literal is negative. Otherwise false. */ bool sign() const { return (rep_ & sign_bit) != 0; } //! Returns var and sign encoded in a unique id. /*! * \note The watch-flag is ignored and thus the id of a literal can be stored in 31-bits. */ uint32 id() const { return rep_ >> flag_bit; } //! Returns the stored representation of this literal. uint32& rep() { return rep_; } uint32 rep() const { return rep_; } //! Creates a literal from an id. static Literal fromId(uint32 id) { assert(id < litIdMax); return Literal(id<(-p)) : posLit(static_cast(p)); } //! Converts the given (non-sentinel) literal to a signed integer s.th. p == toLit(toInt(p)). inline int32 toInt(Literal p) { return p.sign() ? -static_cast(p.var()) : static_cast(p.var()); } //! Always-true literal. // TODO: replace with constant using constexpr ctor once we switch to C++11 inline Literal lit_true() { return Literal(sentVar, false); } //! Always-false literal. // TODO: replace with constant using constexpr ctor once we switch to C++11 inline Literal lit_false() { return Literal(sentVar, true); } //! Returns true if p represents the special variable 0 inline bool isSentinel(Literal p) { return p.var() == sentVar; } // Low-level conversion between Literals and int literals. // We cannot use toInt() here because it is not defined for the // sentinel literals lit_true() and lit_false(). inline int32 encodeLit(Literal x) { return !x.sign() ? static_cast(x.var()+1) : -static_cast(x.var()+1); } inline Var decodeVar(int32 x) { return static_cast(x >= 0 ? x : -x) - 1; } inline Literal decodeLit(int32 x) { return Literal(decodeVar(x), x < 0); } inline unsigned hashId(unsigned key) { key = ~key + (key << 15); key ^= (key >> 11); key += (key << 3); key ^= (key >> 5); key += (key << 10); key ^= (key >> 16); return key; } inline uint32 hashLit(Literal p) { return hashId(p.id()); } //! A signed integer type used to represent weights. typedef int32 weight_t; //! A signed integer type used to represent sums of weights. typedef int64 wsum_t; #define CLASP_WEIGHT_T_MAX ( 2147483647) #define CLASP_WEIGHT_T_MIN (-2147483647 - 1) #define CLASP_WEIGHT_SUM_MAX INT64_MAX #define CLASP_WEIGHT_SUM_MIN INT64_MIN typedef PodVector::type VarVec; //!< A vector of variables. typedef PodVector::type LitVec; //!< A vector of literals. typedef PodVector::type WeightVec; //!< A vector of weights. typedef PodVector::type SumVec; //!< A vector of sums of weights. typedef std::pair WeightLiteral; //!< A literal associated with a weight. typedef PodVector::type WeightLitVec; //!< A vector of weight-literals. /////////////////////////////////////////////////////////////////////////////// // Truth values /////////////////////////////////////////////////////////////////////////////// typedef uint8 ValueRep; //!< Type of the three value-literals. const ValueRep value_true = 1; //!< Value used for variables that are true. const ValueRep value_false = 2; //!< Value used for variables that are false. const ValueRep value_free = 0; //!< Value used for variables that are unassigned. typedef PodVector::type ValueVec; //! Returns the value that makes the literal lit true. /*! * \param lit The literal for which the true-value should be determined. * \return * - value_true iff lit is a positive literal * - value_false iff lit is a negative literal. * . */ inline ValueRep trueValue(const Literal& lit) { return 1 + lit.sign(); } //! Returns the value that makes the literal lit false. /*! * \param lit The literal for which the false-value should be determined. * \return * - value_false iff lit is a positive literal * - value_true iff lit is a negative literal. * . */ inline ValueRep falseValue(const Literal& lit) { return 1 + !lit.sign(); } //! Returns the sign that matches the value. /*! * \return * - false iff v == value_true * - true otherwise */ inline bool valSign(ValueRep v) { return v != value_true; } //@} } #endif clingo-5.2.2/clasp/clasp/logic_program.h000066400000000000000000000747261320011352300202020ustar00rootroot00000000000000// // Copyright (c) 2013-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_LOGIC_PROGRAM_H_INCLUDED #define CLASP_LOGIC_PROGRAM_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include namespace Clasp { namespace Asp { /*! * \file * \defgroup asp Asp * \brief Classes and functions for defining logic programs. * \ingroup problem */ //@{ //! A struct for counting program rules and directives. struct RuleStats { typedef uint32& Ref_t; typedef uint32 const& CRef_t; //! Rules and directives counted by this object. enum Key { Normal = Head_t::Disjunctive,//!< Normal or disjunctive rules. Choice = Head_t::Choice, //!< Choice rules. Minimize , //!< Distinct minimize constraints. Acyc , //!< Edge directives. Heuristic , //!< Heuristic directives. Key__num }; //! Returns a string representation of the given key. static const char* toStr(int k); //! Returns the number of keys distinguished by this type. static uint32 numKeys() { return Key__num; } //! Updates the number of rules of the given type. void up(Key k, int amount) { key[k] += static_cast(amount); } //! Returns the number of rules of the given type. Ref_t operator[](int k) { return key[k]; } //! @copydoc operator[](int k) CRef_t operator[](int k) const { return key[k]; } //! Returns the sum of all rules. uint32 sum() const; uint32 key[Key__num]; //!< @private }; //! A struct for counting distinct program bodies. struct BodyStats { typedef uint32& Ref_t; typedef uint32 const& CRef_t; //! Body types distinguished by this object. typedef Body_t Key; //! Returns a string representation of the given key. static const char* toStr(int k); //! Returns the number of keys distinguished by this type. static uint32 numKeys() { return Body_t::eMax + 1; } //! Updates the number of bodies of the given type. void up(Key k, int amount) { key[k] += static_cast(amount); } //! Returns the number of bodies of the given type. Ref_t operator[](int k) { return key[k]; } //! @copydoc operator[](int k) CRef_t operator[](int k) const { return key[k]; } //! Returns the sum of all bodies. uint32 sum() const; uint32 key[Body_t::eMax + 1]; //!< @private }; //! A type for maintaining a set of program statistics. class LpStats { public: LpStats() { reset(); } void reset(); //! Returns the sum of all equivalences. uint32 eqs() const { return eqs(Var_t::Atom) + eqs(Var_t::Body) + eqs(Var_t::Hybrid); } //! Returns the number of equivalences of the given type. uint32 eqs(VarType t) const { return eqs_[t-1]; } //! Increments the number of equivalences of the given type. void incEqs(VarType t) { ++eqs_[t-1]; } //! Computes *this += o. void accu(const LpStats& o); RuleStats rules[2]; /**< RuleStats (initial, final). */ BodyStats bodies[2]; /**< BodyStats (initial, final). */ uint32 atoms; /**< Number of program atoms. */ uint32 auxAtoms; /**< Number of aux atoms created. */ uint32 disjunctions[2]; /**< Number of disjunctions (initial, non-hcf). */ uint32 sccs; /**< How many strongly connected components? */ uint32 nonHcfs; /**< How many non head-cycle free components?*/ uint32 gammas; /**< How many non-hcf gamma rules. */ uint32 ufsNodes; /**< How many nodes in the positive dependency graph? */ // StatisticObject static uint32 size(); static const char* key(uint32 i); StatisticObject at(const char* k) const; private: uint32 eqs_[3]; }; //! Exception type for signaling an invalid incremental program update. class RedefinitionError : public std::logic_error { public: explicit RedefinitionError(unsigned atomId, const char* atomName = ""); unsigned atom() const { return atomId_; } private: unsigned atomId_; }; using Potassco::TheoryData; struct MapLit_t { POTASSCO_ENUM_CONSTANTS(MapLit_t, Raw = 0, Refined = 1); }; //! A class for defining a logic program. /*! * Use this class to specify a logic program. Once the program is completly defined, * call endProgram() to load the logic program into a SharedContext object. */ class LogicProgram : public ProgramBuilder { public: LogicProgram(); ~LogicProgram(); //! Defines the possible modes for handling extended rules, i.e. choice, cardinality, and weight rules. enum ExtendedRuleMode { mode_native = 0, //!< Handle extended rules natively. mode_transform = 1, //!< Transform extended rules to normal rules. mode_transform_choice = 2, //!< Transform only choice rules to normal rules. mode_transform_card = 3, //!< Transform only cardinality rules to normal rules. mode_transform_weight = 4, //!< Transform cardinality- and weight rules to normal rules. mode_transform_scc = 5, //!< Transform recursive cardinality- and weight rules to normal rules. mode_transform_nhcf = 6, //!< Transform cardinality- and weight rules in non-hcf components to normal rules. mode_transform_integ = 7, //!< Transform cardinality-based integrity constraints. mode_transform_dynamic= 8 //!< Heuristically decide whether or not to transform a particular extended rule. }; //! Options for the Asp-Preprocessor. struct AspOptions { static const uint32 MAX_EQ_ITERS = static_cast( (1u<<25)-1 ); typedef ExtendedRuleMode TrMode; AspOptions() { std::memset(this, 0, sizeof(AspOptions)); iters = 5; } AspOptions& iterations(uint32 it) { iters = it;return *this;} AspOptions& depthFirst() { dfOrder = 1; return *this;} AspOptions& backpropagate() { backprop= 1; return *this;} AspOptions& noScc() { noSCC = 1; return *this;} AspOptions& noEq() { iters = 0; return *this;} AspOptions& disableGamma() { noGamma = 1; return *this;} AspOptions& ext(ExtendedRuleMode m) { erMode = m; return *this;} AspOptions& distinctTrue() { distTrue= 1; return *this;} TrMode erMode; //!< How to handle extended rules? uint32 iters : 26;//!< Number of iterations in eq-preprocessing or 0 to disable. uint32 noSCC : 1;//!< Disable scc checking? uint32 suppMod : 1;//!< Disable scc checking and compute supported models. uint32 dfOrder : 1;//!< Visit nodes in eq-preprocessing in depth-first order? uint32 backprop : 1;//!< Enable backpropagation during preprocessing? uint32 oldMap : 1;//!< Use old and larger mapping for disjunctive programs. uint32 noGamma : 1;//!< Disable creation of (shifted) gamma rules for non-hcf disjunctions? uint32 distTrue : 1;//!< Add distinct true var for each step instead of one for all steps. }; /*! * \name Step control functions */ //@{ //! Starts the definition of a logic program. LogicProgram& start(SharedContext& ctx, const AspOptions& opts = AspOptions()) { startProgram(ctx); setOptions(opts); return *this; } //! Sets the mode for handling extended rules (default: mode_native). void setExtendedRuleMode(ExtendedRuleMode m) { opts_.ext(m); } //! Enable distinct true vars for incremental steps. void enableDistinctTrue(); //! Sets preprocessing options. void setOptions(const AspOptions& opts); //! Sets the configuration to be used for checker solvers in disjunctive LP solving. void setNonHcfConfiguration(Configuration* c){ nonHcfs_.config = c; } //! Unfreezes a currently frozen program and starts an incremental step. /*! * If a program is to be defined incrementally, this function must be called * exactly once for each step before any new rules or atoms are added. * \note Program update only works correctly under the following assumptions: * - Atoms introduced in step i are either: * - solely defined in step i OR, * - marked as frozen in step i and solely defined in step i+k OR, * - forced to false by a compute statement in step 0. * * \pre The program is either frozen or at step 0. * \post The program is no longer frozen and calling program mutating functions is valid again. * \throws std::logic_error precondition is violated. * \note The function is an alias for ProgramBuilder::updateProgram(). */ bool update() { return updateProgram(); } //! Finishes the definition of the logic program (or its current increment). /*! * Applies program mutating operations issued in the current step and transforms * the new program into the solver's internal representation. * * \return false if the program is conflicting, true otherwise. * * \post * - If true is returned, the program is considered to be "frozen" and calling * program mutating functions is invalid until the next call to update(). * - If false is returned, the state of the object is undefined and start() * and dispose() are the only remaining valid operations. * . * \note The function is an alias for ProgramBuilder::endProgram(). */ bool end() { return endProgram(); } //! Visits the the simplified program by notifying out on its elements. void accept(Potassco::AbstractProgram& out); //! Disposes (parts of) the internal representation of the logic program. /*! * \param forceFullDispose If set to true, the whole program is disposed. Otherwise, * only the rules (of the current step) are disposed but atoms and any incremental * control data remain. */ void dispose(bool forceFullDispose); //! Clones the program and adds it to the given ctx. /* * \pre The program is currently frozen. */ bool clone(SharedContext& ctx); //@} /*! * \name Program mutating functions * * Functions in this group shall only be called if the program is currently not * frozen. That is, only between the call to start() (resp. update() if in * incremental setting) and end(). A std::logic_error is raised if this precondition is violated. * */ //@{ //! Adds a new atom to the program and returns the new atom's id. Atom_t newAtom(); //! Sets atomId as the last input atom of the current step. /*! * All (new or existing) atoms with a larger id than atomId * are considered to be auxiliary and automatically removed before * a new incremental step is started. * * \pre atomId >= startAtom() * \post startAuxAtom() == atomId + 1 */ void setMaxInputAtom(uint32 atomId); //! Adds a new conjunctive condition to the program. /*! * \param cond A (possibly empty) list of atom literals. * \return The id of the new condition, which can be later passed to * extractCondition() or getLiteral(). */ Id_t newCondition(const Potassco::LitSpan& cond); //! Adds the given string to the problem's output table. /*! * \param str The string to add. * \param cond The condition under which str should be considered part of a model. */ LogicProgram& addOutput(const ConstString& str, const Potassco::LitSpan& cond); LogicProgram& addOutput(const ConstString& str, Id_t cond); //! Adds the given atoms to the set of projection variables. LogicProgram& addProject(const Potassco::AtomSpan& atoms); //! Protects an otherwise undefined atom from preprocessing. /*! * If the atom is defined in this or a previous step, the operation has no effect. * \note If atomId is not yet known, an atom with the given id is implicitly created. * \note The second parameter defines the assumption that shall hold during solving, i.e. * - posLit(atomId), if value is value_true, * - negLit(atomId), if value is value_false, or * - no assumption, if value is value_free. * * \see ProgramBuilder::getAssumptions(LitVec&) const; */ LogicProgram& freeze(Atom_t atomId, ValueRep value = value_false); //! Removes any protection from the given atom. /*! * If the atom is defined in this or a previous step, the operation has no effect. * \note * - The effect is logically equivalent to adding a rule atomId :- false. * - A call to unfreeze() always overwrites a call to freeze() even if the * latter comes after the former * . */ LogicProgram& unfreeze(Atom_t atomId); //! Adds the given rule (or integrity constraint) to the program. /*! * \pre The the rule does not define an atom from a previous incremental step. * * Simplifies the given rule and adds it to the program if it * is neither tautological (e.g. a :- a) nor contradictory (e.g. a :- b, not b). * Atoms in the simplified rule that are not yet known are implicitly created. * * \throws RedefinitionError if the precondition is violated. * \note If the head of the simplified rule mentions an atom from a previous step, * that atom shall either be frozen or false. In the former case, * unfreeze() is implicitly called. In the latter case, the rule is interpreted * as an integrity constraint. */ LogicProgram& addRule(const Rule& rule); LogicProgram& addRule(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body); LogicProgram& addRule(Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& lits); LogicProgram& addRule(Potassco::RuleBuilder& rb); //! Adds the given minimize statement. /*! * \param prio The priority of the minimize statement. * \param lits The literals to minimize. * \note All minimize statements of the same priority are merged into one. */ LogicProgram& addMinimize(weight_t prio, const Potassco::WeightLitSpan& lits); //! Adds an edge to the extended (user-defined) dependency graph. LogicProgram& addAcycEdge(uint32 n1, uint32 n2, const Potassco::LitSpan& condition) { return addAcycEdge(n1, n2, newCondition(condition)); } LogicProgram& addAcycEdge(uint32 n1, uint32 n2, Id_t cond); //! Adds a conditional domain heuristic directive to the program. LogicProgram& addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio, const Potassco::LitSpan& condition) { return addDomHeuristic(atom, t, bias, prio, newCondition(condition)); } LogicProgram& addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio, Id_t cond); //! Adds an unconditional domain heuristic directive to the program. LogicProgram& addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio); //! Forces the given literals to be true during solving. /*! * Assumptions are retracted on the next program update. */ LogicProgram& addAssumption(const Potassco::LitSpan& cube); //! Adds or updates the given external atom. /*! * \see LogicProgram::freeze(Atom_t atomId, ValueRep value); * \see LogicProgram::unfreeze(Atom_t atomId); */ LogicProgram& addExternal(Atom_t atomId, Potassco::Value_t value); //! Returns an object for adding theory data to this program. TheoryData& theoryData(); //@} /*! * \name Query functions * * Functions in this group are useful to query important information * once the program is frozen, i.e. after end() was called. * They do not throw exceptions. */ //@{ //! Returns whether the program can be represented in internal smodels format. bool supportsSmodels() const; //! Returns whether the program is to be defined incrementally. bool isIncremental() const { return incData_ != 0; } //! Returns whether the program contains any minimize statements. bool hasMinimize() const { return !minimize_.empty(); } //! Returns whether the program contains any theory data. bool hasTheoryData() const { return theory_ != 0; } //! Returns the number of atoms in the logic program. uint32 numAtoms() const { return (uint32)atoms_.size()-1; } //! Returns the number of bodies in the current (slice of the) logic program. uint32 numBodies() const { return (uint32)bodies_.size(); } //! Returns the number of disjunctive heads. uint32 numDisjunctions() const { return (uint32)disjunctions_.size(); } //! Returns the id of the first atom of the current step. Atom_t startAtom() const { return input_.lo; } //! Returns an id one past the last valid atom id in the program. Atom_t endAtom() const { return numAtoms() + 1; } //! Returns the id of the first atom that is not an input atom or endAtom() if no such atoms exists. Atom_t startAuxAtom() const; //! Returns whether a is an atom in the (simplified) program. bool inProgram(Atom_t a) const; //! Returns whether a is an external atom, i.e. is frozen in this step. bool isExternal(Atom_t a) const; //! Returns whether a occurs in the head of a rule. bool isDefined(Atom_t a) const; //! Returns whether a is a fact. bool isFact(Atom_t a) const; //! Returns the solver literal that is associated with the given atom or condition. /*! * \pre id is the id of a valid atom literal or was previously returned by newCondition(). * \note Untill end() is called, the function returns lit_false() for * all atoms and conditions defined in the current step. * \note For an atom literal x with Potassco::atom(x) == a, * getLiteral(Potassco::id(x)) returns * getLiteral(a), iff x == a, or * ~getLiteral(a), iff x == -a. * * \note If mode is MapLit_t::Raw, the function simply returns the literal that * was set during preprocessing. Otherwise, it also consideres equivalences * induced by domain heuristic directives and/or step-local true vars. * * \see enableDistinctTrue() */ Literal getLiteral(Id_t id, MapLit_t mode = MapLit_t::Raw) const; //! Returns the atom literals belonging to the given condition. /*! * \pre cId was previously returned by newCondition() in the current step. */ bool extractCondition(Id_t cId, Potassco::LitVec& lits) const; LpStats stats; //!< Statistics of the current step. //@} /*! * \name Implementation functions * Low-level implementation functions. Use with care and only if you * know what you are doing! */ //@{ typedef VarVec::const_iterator VarIter; typedef PrgHead*const* HeadIter; typedef std::pair EdgeRange; typedef std::pair HeadRange; struct SRule { SRule() : hash(0), pos(0), bid(varMax) {} uint32 hash; // hash value of the body uint32 pos; // positive size of body uint32 bid; // id of existing body or varMax }; const AspOptions& options() const { return opts_; } bool hasConflict() const { return getTrueAtom()->literal() != lit_true(); } bool ok() const { return !hasConflict() && ProgramBuilder::ok(); } PrgAtom* getAtom(Id_t atomId)const { return atoms_[atomId]; } PrgHead* getHead(PrgEdge it) const { return it.isAtom() ? (PrgHead*)getAtom(it.node()) : (PrgHead*)getDisj(it.node()); } PrgNode* getSupp(PrgEdge it) const { return it.isBody() ? (PrgNode*)getBody(it.node()) : (PrgNode*)getDisj(it.node()); } Id_t getRootId(Id_t atom)const { return getEqNode(atoms_, atom); } PrgAtom* getRootAtom(Id_t a) const { return getAtom(getRootId(a)); } PrgBody* getBody(Id_t bodyId)const { return bodies_[bodyId]; } Id_t getEqBody(Id_t b) const { return getEqNode(bodies_, b); } PrgDisj* getDisj(Id_t disjId)const { return disjunctions_[disjId]; } HeadIter disj_begin() const { return disjunctions_.empty() ? 0 : reinterpret_cast(&disjunctions_[0]); } HeadIter disj_end() const { return disj_begin() + numDisjunctions(); } HeadIter atom_begin() const { return reinterpret_cast(&atoms_[0]); } HeadIter atom_end() const { return atom_begin() + (numAtoms()+1); } VarIter unfreeze_begin() const { return incData_?incData_->unfreeze.begin() : propQ_.end(); } VarIter unfreeze_end() const { return incData_?incData_->unfreeze.end() : propQ_.end(); } bool validAtom(Id_t aId) const { return aId < (uint32)atoms_.size(); } bool validBody(Id_t bId) const { return bId < numBodies(); } bool validDisj(Id_t dId) const { return dId < numDisjunctions(); } bool isFact(PrgAtom* a) const; const char*findName(Atom_t x) const; bool simplifyRule(const Rule& r, Potassco::RuleBuilder& out, SRule& meta); Atom_t falseAtom(); VarVec& getSupportedBodies(bool sorted); uint32 update(PrgBody* b, uint32 oldHash, uint32 newHash); bool assignValue(PrgAtom* a, ValueRep v, PrgEdge reason); bool assignValue(PrgHead* h, ValueRep v, PrgEdge reason); bool propagate(bool backprop); PrgAtom* mergeEqAtoms(PrgAtom* a, Id_t rootAtom); PrgBody* mergeEqBodies(PrgBody* b, Id_t rootBody, bool hashEq, bool atomsAssigned); bool propagate() { return propagate(options().backprop != 0); } void setConflict() { getTrueAtom()->setLiteral(lit_false()); } AtomState& atomState() { return atomState_; } void addMinimize(); // ------------------------------------------------------------------------ // Statistics void incTrAux(uint32 n) { stats.auxAtoms += n; } void incEqs(VarType t) { stats.incEqs(t); } void upStat(RuleStats::Key k, int n = 1){ stats.rules[statsId_].up(k, n); } void upStat(Body_t k, int n = 1) { stats.bodies[statsId_].up(k, n); } void upStat(Head_t k, int n = 1) { stats.rules[statsId_].up(static_cast(unsigned(k)), n); } // ------------------------------------------------------------------------ //@} private: LogicProgram(const LogicProgram&); LogicProgram& operator=(const LogicProgram&); struct DlpTr; struct AcycArc { Id_t cond; uint32 node[2]; }; struct DomRule { uint32 atom : 29; uint32 type : 3; Id_t cond; int16 bias; uint16 prio; }; struct Eq { Atom_t var; Literal lit; }; struct TFilter { bool operator()(const Potassco::TheoryAtom& atom) const; LogicProgram* self; }; struct Min { weight_t prio; Potassco::WLitVec lits; }; struct CmpMin { bool operator()(const Min* m1, const Min* m2) const { return m1->prio < m2->prio; } }; typedef Potassco::RuleBuilder RuleBuilder; typedef std::pair ShowPair; typedef PodVector::type ShowVec; typedef PodVector::type DomRules; typedef PodVector::type AcycRules; typedef PodVector::type RuleList; typedef PodVector::type MinList; typedef PodVector::type SccMap; typedef PodVector::type EqVec; typedef POTASSCO_EXT_NS::unordered_multimap IndexMap; typedef IndexMap::iterator IndexIter; typedef std::pair IndexRange; typedef Potassco::WLitVec LpWLitVec; typedef Potassco::LitVec LpLitVec; typedef Range AtomRange; // ------------------------------------------------------------------------ // virtual overrides bool doStartProgram(); bool doUpdateProgram(); bool doEndProgram(); void doGetAssumptions(LitVec& out) const; ProgramParser* doCreateParser(); int doType() const { return Problem_t::Asp; } // ------------------------------------------------------------------------ // Program definition bool isNew(Atom_t atomId) const { return atomId >= startAtom(); } PrgAtom* resize(Atom_t atomId); void pushFrozen(PrgAtom* atom, ValueRep v); void addRule(const Rule& r, const SRule& meta); void addFact(const Potassco::AtomSpan& head); void addIntegrity(const Rule& b, const SRule& meta); bool handleNatively(const Rule& r) const; bool transformNoAux(const Rule& r) const; void freezeTheory(); void transformExtended(); void transformIntegrity(uint32 nAtoms, uint32 maxAux); PrgBody* getBodyFor(const Rule& r, const SRule& m, bool addDeps = true); PrgBody* getTrueBody(); PrgDisj* getDisjFor(const Potassco::AtomSpan& heads, uint32 headHash); PrgBody* assignBodyFor(const Rule& r, const SRule& m, EdgeType x, bool strongSimp); bool equalLits(const PrgBody& b, const WeightLitSpan& lits) const; bool simplifyNormal(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body, RuleBuilder& out, SRule& info); bool simplifySum(Head_t ht, const Potassco::AtomSpan& head, const Potassco::Sum_t& body, RuleBuilder& out, SRule& info); bool pushHead(Head_t ht, const Potassco::AtomSpan& head, weight_t slack, RuleBuilder& out); ValueRep litVal(const PrgAtom* a, bool pos) const; uint32 findBody(uint32 hash, Body_t type, uint32 size, weight_t bound = -1, Potassco::WeightLit_t* wlits = 0); uint32 findEqBody(const PrgBody* b, uint32 hash); uint32 removeBody(PrgBody* b, uint32 oldHash); Literal getEqAtomLit(Literal lit, const BodyList& supports, Preprocessor& p, const SccMap& x); bool positiveLoopSafe(PrgBody* b, PrgBody* root) const; void prepareExternals(); void updateFrozenAtoms(); void normalize(); template Id_t getEqNode(C& vec, Id_t id) const { if (!vec[id]->eq()) return id; PrgNode* n = vec[id], *r; Id_t root = n->id(); for (r = vec[root]; r->eq(); r = vec[root]) { // n == r and r == r' -> n == r' assert(root != r->id()); n->setEq(root = r->id()); } return root; } bool checkBody(const PrgBody& rhs, Body_t type, uint32 size, weight_t bound) const { return (rhs.relevant() || (rhs.eq() && getBody(getEqBody(rhs.id()))->relevant())) && rhs.type() == type && rhs.size() == size && rhs.bound() == bound; } // ------------------------------------------------------------------------ // Nogood creation void prepareProgram(bool checkSccs); void prepareOutputTable(); void finalizeDisjunctions(Preprocessor& p, uint32 numSccs); void prepareComponents(); bool addConstraints(); void addAcycConstraint(); void addDomRules(); // ------------------------------------------------------------------------ void deleteAtoms(uint32 start); PrgAtom* getTrueAtom() const { return atoms_[0]; } RuleBuilder rule_; // temporary: active rule AtomState atomState_; // which atoms appear in the active rule? IndexMap bodyIndex_; // hash -> body id IndexMap disjIndex_; // hash -> disjunction id IndexMap domEqIndex_; // maps eq atoms modified by dom heuristic to aux vars BodyList bodies_; // all bodies AtomList atoms_; // all atoms DisjList disjunctions_;// all (head) disjunctions MinList minimize_; // list of minimize rules RuleList extended_; // extended rules to be translated ShowVec show_; // shown atoms/conditions VarVec initialSupp_; // bodies that are (initially) supported VarVec propQ_; // assigned atoms VarVec frozen_; // list of frozen atoms NonHcfSet nonHcfs_; // set of non-hcf sccs TheoryData* theory_; // optional map of theory data AtomRange input_; // input atoms of current step int statsId_; // which stats to update (0 or 1) struct Aux { AtomList scc; // atoms that are strongly connected DomRules dom; // list of domain heuristic directives AcycRules acyc; // list of user-defined edges for acyclicity check LpLitVec assume; // set of assumptions VarVec project; // atoms in projection directives VarVec external; // atoms in external directives }* auxData_; // additional state for handling extended constructs struct Incremental { // first: last atom of step, second: true var typedef std::pair StepTrue; typedef PodVector::type TrueVec; Incremental(); uint32 startScc; // first valid scc number in this iteration VarVec unfreeze; // list of atoms to unfreeze in this step VarVec doms; // list of atom variables with domain modification TrueVec steps; // map of steps to true var }* incData_; // additional state for handling incrementally defined programs AspOptions opts_; // preprocessing }; //! Returns the internal solver literal that is associated with the given atom literal. /*! * \pre The prg is frozen and atomLit is a known atom in prg. */ inline Literal solverLiteral(const LogicProgram& prg, Potassco::Lit_t atomLit) { POTASSCO_REQUIRE(prg.frozen() && prg.validAtom(Potassco::atom(atomLit))); return prg.getLiteral(Potassco::id(atomLit)); } //! Adapts a LogicProgram object to the Potassco::AbstractProgram interface. class LogicProgramAdapter : public Potassco::AbstractProgram { public: LogicProgramAdapter(LogicProgram& prg); void initProgram(bool inc); void beginStep(); void endStep(); void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body); void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body); void minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits); void project(const Potassco::AtomSpan& atoms); void output(const Potassco::StringSpan& str, const Potassco::LitSpan& cond); void external(Potassco::Atom_t a, Potassco::Value_t v); void assume(const Potassco::LitSpan& lits); void heuristic(Potassco::Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, const Potassco::LitSpan& cond); void acycEdge(int s, int t, const Potassco::LitSpan& cond); void theoryTerm(Potassco::Id_t termId, int number); void theoryTerm(Potassco::Id_t termId, const Potassco::StringSpan& name); void theoryTerm(Potassco::Id_t termId, int cId, const Potassco::IdSpan& args); void theoryElement(Potassco::Id_t elementId, const Potassco::IdSpan& terms, const Potassco::LitSpan& cond); void theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements); void theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements, Potassco::Id_t op, Potassco::Id_t rhs); protected: Asp::LogicProgram* lp_; bool inc_; }; //@} } } // end namespace Asp #endif clingo-5.2.2/clasp/clasp/logic_program_types.h000066400000000000000000000663561320011352300214260ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_LOGIC_PROGRAM_TYPES_H_INCLUDED #define CLASP_LOGIC_PROGRAM_TYPES_H_INCLUDED #ifdef _MSC_VER #pragma once #endif /*! * \file * \brief Basic types for working with a logic program. */ #include #include #include #include namespace Potassco { typedef Clasp::PodVector::type LitVec; typedef Clasp::PodVector::type WLitVec; } namespace Clasp { class ClauseCreator; using Potassco::idMax; namespace Asp { typedef PodVector::type AtomList; typedef PodVector::type BodyList; typedef PodVector::type DisjList; const ValueRep value_weak_true = 3; /**< true but no proof */ using Potassco::Atom_t; using Potassco::Id_t; /*! * \addtogroup asp */ //@{ //! A node of a program-dependency graph. /*! * A node represents a relevant part in a logic program. Each node * has at least a literal and a value. */ class PrgNode { public: //! Supported node types. enum Type { Atom = 0u, Body = 1u, Disj = 2u }; static const uint32 noScc = (1u << 27)-1; static const uint32 noNode = (1u << 28)-1; static const uint32 noLit = 1; //! Creates a new node that corresponds to a literal that is false. explicit PrgNode(uint32 id, bool checkScc = true); //! Is the node still relevant or removed() resp. eq()? bool relevant() const { return eq_ == 0; } //! Was the node removed? bool removed() const { return eq_ != 0 && id_ == noNode; } //! Ignore the node during scc checking? bool ignoreScc()const { return noScc_ != 0; } //! Returns true if this node is equivalent to some other node. /*! * If eq() is true, the node is no longer relevant and must not be used any further. * The only sensible operation is to call id() in order to get the id of the node * that is equivalent to this node. */ bool eq() const { return eq_ != 0 && id_ != noNode; } bool seen() const { return seen_ != 0; } //! Returns true if node has an associated variable in a solver. bool hasVar() const { return litId_ != noLit; } //! Returns the variable associated with this node or sentVar if no var is associated with this node. Var var() const { return litId_ >> 1; } //! Returns the literal associated with this node or a sentinel literal if no var is associated with this node. Literal literal() const { return Literal::fromId(litId_); } //! Returns the value currently assigned to this node. ValueRep value() const { return val_; } //! Returns the current id of this node. uint32 id() const { return id_; } //! Returns the literal that must be true in order to fulfill the truth-value of this node. Literal trueLit() const { return value() == value_free ? lit_true() : literal() ^ (value() == value_false); } /*! * \name implementation functions * Low-level implementation functions. Use with care and only if you * know what you are doing! */ //@{ void setLiteral(Literal x) { litId_ = x.id(); } void clearLiteral(bool clVal){ litId_ = noLit; if (clVal) val_ = value_free; } void setValue(ValueRep v) { val_ = v; } void setEq(uint32 eqId) { id_ = eqId; eq_ = 1; seen_ = 1; } void setIgnoreScc(bool b) { noScc_ = (uint32)b; } void markRemoved() { if (!eq()) setEq(noNode); } void setSeen(bool b) { seen_ = uint32(b); } void resetId(uint32 id, bool seen) { id_ = id; eq_ = 0; seen_ = (uint32)seen; } bool assignValueImpl(ValueRep v, bool noWeak) { if (v == value_weak_true && noWeak) { v = value_true; } if (value() == value_free || v == value() || (value() == value_weak_true && v == value_true)) { setValue(v); return true; } return v == value_weak_true && value() == value_true; } //@} protected: uint32 litId_ : 31; // literal-id in solver uint32 noScc_ : 1; // ignore during scc checks? uint32 id_ : 28; // own id/eq-id/root-id/ufs-id uint32 val_ : 2; // assigned value uint32 eq_ : 1; // removed or eq to some other node? uint32 seen_ : 1; // marked as seen? private: PrgNode(const PrgNode&); PrgNode& operator=(const PrgNode&); }; typedef PrgNode::Type NodeType; //! An edge of a program-dependency graph. /*! * Currently, clasp distinguishes four types of edges: * - a Normal edge stipulates an implication between body and head, * i.e. tableau-rules FTA and BFA for atoms. * - a Choice edge only stipulates a support. * - a Gamma edge is like a Normal edge that is only considered during * nogood creation but ignored in the dependency graph. * - a GammaChoice edge is like a Gamma edge but only stipulates a support. * The head of a rule is either an atom or a disjunction. */ struct PrgEdge { //! Type of edge. enum Type { Normal = 0, Gamma = 1, Choice = 2, GammaChoice = 3 }; static PrgEdge noEdge() { PrgEdge x; x.rep = UINT32_MAX; return x; } template static PrgEdge newEdge(const NT& n, Type eType) { // 28-bit node id, 2-bit node type, 2-bit edge type PrgEdge x = { (n.id() << 4) | (static_cast(n.nodeType()) << 2) | eType }; return x; } //! Returns the id of the adjacent node. uint32 node() const { return rep >> 4; } //! Returns the type of this edge. Type type() const { return Type(rep & 3u); } //! Returns the type of adjacent node. NodeType nodeType() const { return NodeType((rep >> 2) & 3u); } //! Returns true if edge has normal semantic (normal edge or gamma edge). bool isNormal() const { return (rep & 2u) == 0; } //! Returns true if edge has choice semantic. bool isChoice() const { return (rep & 2u) != 0; } //! Returns true if the edge is a gamma (aux normal) edge. bool isGamma() const { return (rep & 1u) != 0; } //! Returns true if the adjacent node is a body. bool isBody() const { return nodeType() == PrgNode::Body; } //! Returns true if the adjacant node is an atom. bool isAtom() const { return nodeType() == PrgNode::Atom; } //! Returns true if the adjacent node is a disjunction. bool isDisj() const { return nodeType() == PrgNode::Disj; } bool operator< (PrgEdge rhs) const { return rep < rhs.rep; } bool operator==(PrgEdge rhs) const { return rep == rhs.rep; } uint32 rep; }; typedef PrgEdge::Type EdgeType; typedef const PrgEdge* EdgeIterator; typedef bk_lib::pod_vector EdgeVec; inline bool isChoice(EdgeType t) { return t >= PrgEdge::Choice; } using Potassco::Body_t; using Potassco::Head_t; using Potassco::WeightLitSpan; typedef Potassco::Rule_t Rule; //! A class for translating extended rules to normal rules. class RuleTransform { public: //! Interface that must be implemented to get the result of a transformation. struct ProgramAdapter { virtual Atom_t newAtom() = 0; virtual void addRule(const Rule& r) = 0; protected: ~ProgramAdapter() {} }; //! Supported transformation strategies. enum Strategy { strategy_default, strategy_no_aux, strategy_allow_aux }; RuleTransform(ProgramAdapter& prg); RuleTransform(LogicProgram& prg); ~RuleTransform(); //! Transforms the given (extended) rule to a set of normal rules. uint32 transform(const Rule& r, Strategy s = strategy_default); private: RuleTransform(const RuleTransform&); RuleTransform& operator=(const RuleTransform&); struct Impl; Impl* impl_; }; //! A set of flags used during rule simplification. class AtomState { public: static const uint8 pos_flag = 0x1u; //!< In positive body of active rule static const uint8 neg_flag = 0x2u; //!< In negative body of active rule static const uint8 head_flag = 0x4u; //!< In normal head of active rule static const uint8 choice_flag = 0x8u; //!< In choice head of active rule static const uint8 disj_flag = 0x10u;//!< In disjunctive head of active rule static const uint8 rule_mask = 0x1Fu;//!< In active rule static const uint8 fact_flag = 0x20u;//!< Atom is a fact (sticky) static const uint8 false_flag = 0x40u;//!< Atom is false (sticky) static const uint8 simp_mask = 0x7fu;//!< In active rule or assigned static const uint8 dom_flag = 0x80u;//!< Var of atom is a dom var (sticky) AtomState() {} void swap(AtomState& o) { state_.swap(o.state_); } //! Does t.node() appear in the head of the active rule? bool inHead(PrgEdge t) const { return isSet(t.node(), headFlag(t)); } bool inHead(Atom_t atom) const { return isSet(atom, head_flag); } //! Does p appear in the body of the active rule? bool inBody(Literal p) const { return isSet(p.var(), pos_flag+p.sign()); } bool isSet(Var v, uint8 f) const { return v < state_.size() && (state_[v] & f) != 0; } bool isFact(Var v) const { return isSet(v, fact_flag); } //! Mark v as a head of the active rule. void addToHead(Atom_t v) { set(v, head_flag); } void addToHead(PrgEdge t) { set(t.node(), headFlag(t)); } //! Mark p as a literal contained in the active rule. void addToBody(Literal p) { set(p.var(), pos_flag+p.sign()); } void set(Var v, uint8 f) { grow(v); state_[v] |= f; } void clear(Var v, uint8 f) { if (v < state_.size()) { state_[v] &= ~f; } } void clearRule(Var v) { clear(v, rule_mask); } void clearHead(PrgEdge t) { clear(t.node(), headFlag(t)); } void clearBody(Literal p) { clear(p.var(), pos_flag+p.sign()); } void resize(uint32 sz) { state_.resize(sz); } template bool allMarked(IT first, IT last, uint8 f) const { for (; first != last; ++first) { if (!isSet(*first, f)) return false; } return true; } bool inBody(const Literal* first, const Literal* last) const { bool all = true; for (; first != last && (all = inBody(*first)) == true; ++first) { ; } return all; } private: typedef PodVector::type StateVec; void grow(Var v) { if (v >= state_.size()) { state_.resize(v+1); } } uint8 headFlag(PrgEdge t) const { return t.isAtom() ? (head_flag << uint8(t.isChoice())) : disj_flag; } StateVec state_; }; //! A head node of a program-dependency graph. /*! * A head node is either an atom or a disjunction * and stores its possible supports. */ class PrgHead : public PrgNode { public: enum Simplify { no_simplify = 0, force_simplify = 1 }; typedef EdgeIterator sup_iterator; //! Is the head part of the (simplified) program? bool inUpper() const { return relevant() && upper_ != 0; } //! Is this head an atom? bool isAtom() const { return isAtom_ != 0; } //! Number of supports (rules) for this head. uint32 supports() const { return supports_.size(); } sup_iterator supps_begin()const { return supports_.begin(); } sup_iterator supps_end() const { return supports_.end(); } //! External atom (or defined in a later incremental step)? bool frozen() const { return freeze_ != uint32(freeze_no); } //! If frozen(), value to assume during solving. ValueRep freezeValue()const { return static_cast(freeze_ - uint32(freeze_ != 0)); } //! If frozen(), literal to assume during solving. Literal assumption() const { return freeze_ > uint32(freeze_free) ? literal() ^ (freeze_ == freeze_false) : lit_true(); } //! Adds r as support edge for this node. void addSupport(PrgEdge r){ addSupport(r, force_simplify); } void addSupport(PrgEdge r, Simplify s); //! Removes r from the head's list of supports. void removeSupport(PrgEdge r); void clearSupports(); void clearSupports(EdgeVec& to) { to.swap(supports_); clearSupports(); } //! Removes any superfluous/irrelevant supports. bool simplifySupports(LogicProgram& prg, bool strong, uint32* numDiffSupps = 0); //! Assigns the value v to this head. bool assignValue(ValueRep v) { return assignValueImpl(v, ignoreScc() && !frozen()); } /*! * \name implementation functions * Low-level implementation functions. Use with care and only if you * know what you are doing! */ //@{ void setInUpper(bool b) { upper_ = (uint32)b; } void markDirty() { dirty_ = 1; } void assignVar(LogicProgram& prg, PrgEdge it, bool allowEq = true); NodeType nodeType() const { return isAtom() ? PrgNode::Atom : PrgNode::Disj; } //@} protected: enum FreezeState { freeze_no = 0u, freeze_free = 1u, freeze_true = 2u, freeze_false = 3u }; //! Creates a new node that corresponds to a literal that is false. explicit PrgHead(uint32 id, NodeType t, uint32 data = 0, bool checkScc = true); bool backpropagate(LogicProgram& prg, ValueRep val, bool bpFull); EdgeVec supports_; // possible supports (body or disjunction) uint32 data_ : 27; // number of atoms in disjunction or scc of atom uint32 upper_ : 1; // in (simplified) program? uint32 dirty_ : 1; // is list of supports dirty? uint32 freeze_: 2; // incremental freeze state uint32 isAtom_: 1; // is this head an atom? }; //! An atom in a logic program. /*! * An atom stores the list of bodies depending on it. * Furthermore, once strongly-connected components are identified, * atoms store their SCC-number. All trivial SCCs are represented * with the special SCC-number PrgNode::noScc. */ class PrgAtom : public PrgHead { public: enum Dependency { dep_pos = 0, dep_neg = 1, dep_all = 2 }; typedef LitVec::const_iterator dep_iterator; explicit PrgAtom(uint32 id, bool checkScc = true); NodeType nodeType() const { return PrgNode::Atom; } //! Strongly connected component of this node. uint32 scc() const { return data_; } //! If eq(), stores the literal that is eq to this atom. Literal eqGoal(bool sign) const; //! Returns true if atom belongs to a disjunctive head. bool inDisj() const; /*! * \name forward dependencies (bodies containing this atom) */ //@{ dep_iterator deps_begin() const { return deps_.begin(); } dep_iterator deps_end() const { return deps_.end(); } bool hasDep(Dependency d) const; void addDep(Id_t bodyId, bool pos); void removeDep(Id_t bodyId, bool pos); void clearDeps(Dependency d); //@} /*! * \name implementation functions * Low-level implementation functions. Use with care and only if you * know what you are doing! */ //@{ void setEqGoal(Literal x); bool propagateValue(LogicProgram& prg, bool backprop); bool addConstraints(const LogicProgram& prg, ClauseCreator& c); void setScc(uint32 scc) { data_ = scc; } void markFrozen(ValueRep v){ freeze_ = v + freeze_free; } void clearFrozen() { freeze_ = freeze_no; markDirty(); } //@} private: LitVec deps_; // bodies depending on this atom }; //! A (rule) body in a logic program. class PrgBody : public PrgNode { public: typedef EdgeIterator head_iterator; typedef const Literal* goal_iterator; //! Creates a new body node and (optionally) connects it to its predecessors (i.e. atoms). /*! * \param prg The program in which the new body is used. * \param id The id for the new body node. * \param rule The rule for which a body node is to be created. * \param pos Positive body size. * \param addDeps If true, add an edge between each atom subgoal and the new node. */ static PrgBody* create(LogicProgram& prg, uint32 id, const Rule& rule, uint32 pos, bool addDeps); //! Destroys a body node created via create(). void destroy(); Body_t type() const { return Body_t(static_cast(type_)); } //! Returns the number of atoms in the body. uint32 size() const { return size_; } bool noScc() const { return size() == 0 || goal(0).sign(); } //! Returns the bound of this body, or size() if the body is a normal body. weight_t bound() const { if (type() == Body_t::Normal) return (weight_t)size(); else return hasWeights() ? sumData()->bound : aggData().bound; } //! Returns the sum of the subgoals weights, or size() if the body is not a sum with weights. weight_t sumW() const { return static_cast(!hasWeights() ? (weight_t)size() : sumData()->sumW); } //! Returns the idx'th subgoal as a literal. Literal goal(uint32 idx) const { assert(idx < size()); return *(goals_begin()+idx); } //! Returns the weight of the idx'th subgoal. weight_t weight(uint32 idx)const { assert(idx < size()); return !hasWeights() ? 1 : sumData()->weights[idx]; } //! Returns true if the body node is supported. /*! * A normal body is supported, iff all of its positive subgoals are supported. * A count/sum body is supported if the sum of the weights of the supported positive + * the sum of the negative weights is >= lowerBound(). */ bool isSupported() const { return unsupp_ <= 0; } //! Returns true if this body defines any head. bool hasHeads() const { return isSmallHead() ? head_ != 0 : !largeHead()->empty(); } bool inRule() const { return hasHeads() || freeze_; } head_iterator heads_begin() const { return isSmallHead() ? smallHead() : largeHead()->begin(); } head_iterator heads_end() const { return isSmallHead() ? smallHead()+head_ : largeHead()->end(); } goal_iterator goals_begin() const { return const_cast(this)->goals_begin(); } goal_iterator goals_end() const { return goals_begin() + size(); } //! Adds a rule edge between this body and the given head. /*! * \note * The function also adds a corresponding back edge to the head. * \note * Adding a head invalidates the set property for the heads of this body. * To restore it, call simplifyHeads() */ void addHead(PrgHead* h, EdgeType t); //! Simplifies the heads of this body and establishes set property. /*! * Removes superfluous heads and sets the body to false if for some atom a * in the head of this body B, Ta -> FB. In that case, all heads atoms are removed, because * a false body can't define any atom. * If strong is true, removes head atoms that are not associated with a variable. * \return * setValue(value_false) if setting a head of this body to true would * make the body false (i.e. the body is a selfblocker). Otherwise, true. */ bool simplifyHeads(LogicProgram& prg, bool strong); bool mergeHeads(LogicProgram& prg, PrgBody& heads, bool strong, bool simplify = true); void removeHead(PrgHead* h, EdgeType t); bool hasHead(PrgHead* h, EdgeType t) const; //! Simplifies the body, i.e. its predecessors-lists. /*! * - removes true/false atoms from B+/B- resp. * - removes/merges duplicate subgoals * - checks whether body must be false (e.g. contains false/true atoms in B+/B- resp. or contains p and ~p) * * \pre prg.getBody(id()) == this * * \param[in] prg The program containing this body. * \param[in] strong If true, treats atoms that have no variable associated as false. * \param[out] eqId The id of a body in prg that is equivalent to this body. * * \return * - true if simplification was successful * - false if simplification detected a conflict */ bool simplifyBody(LogicProgram& prg, bool strong, uint32* eqId = 0); //! Calls simplifyBody() and/or simplifyHeads() if necessary. bool simplify(LogicProgram& prg, bool strong, uint32* eqId = 0) { return simplifyBody(prg, strong, eqId) && simplifyHeads(prg, strong); } bool toData(const LogicProgram& prg, Potassco::RuleBuilder& out) const; //! Notifies the body node about the fact that its positive subgoal v is supported. /*! * \return true if the body is now also supported, false otherwise. */ bool propagateSupported(Var /* v */); //! Propagates the assignment of subgoal p. bool propagateAssigned(LogicProgram& prg, Literal p, ValueRep v); //! Propagates the assignment of a head. bool propagateAssigned(LogicProgram& prg, PrgHead* h, EdgeType t); //! Propagates the value of this body. bool propagateValue(LogicProgram& prg, bool backprop); bool propagateValue(LogicProgram& prg); bool addConstraints(const LogicProgram& prg, ClauseCreator& c); void markDirty() { sBody_ = 1; } void markHeadsDirty() { sHead_ = 1; } void markFrozen() { freeze_= 1; } void clearHeads(); bool resetSupported(); void assignVar(LogicProgram& prg); bool assignValue(ValueRep v) { return assignValueImpl(v, noScc()); } uint32 scc(const LogicProgram& prg) const; bool hasWeights() const { return type() == Body_t::Sum; } void clearRule(AtomState& rs) const { for (head_iterator it = heads_begin(), end = heads_end(); it != end; ++it) { rs.clearRule(it->node()); } for (const Literal* it = goals_begin(), *end = it + size(); it != end; ++it) { rs.clearRule(it->var()); } } NodeType nodeType() const { return PrgNode::Body; } private: static const uint32 maxSize = (1u<<26)-1; typedef unsigned char byte_t; POTASSCO_WARNING_BEGIN_RELAXED struct SumData { enum { LIT_OFFSET = sizeof(void*)/sizeof(uint32) }; static SumData* create(uint32 size, weight_t bnd, weight_t ws); void destroy(); weight_t bound; weight_t sumW; weight_t weights[0]; }; struct Agg { union { SumData* sum; weight_t bound; }; Literal lits[0]; }; struct Norm { Literal lits[0]; }; PrgBody(uint32 id, LogicProgram& prg, const Potassco::LitSpan& lits, uint32 pos, bool addDeps); PrgBody(uint32 id, LogicProgram& prg, const Potassco::Sum_t& sum, bool hasWeights, uint32 pos, bool addDeps); void init(Body_t t, uint32 sz); ~PrgBody(); uint32 findLit(const LogicProgram& prg, Literal p) const; bool normalize(const LogicProgram& prg, weight_t bound, weight_t sumW, weight_t reachW, uint32& hashOut); void prepareSimplifyHeads(LogicProgram& prg, AtomState& rs); bool simplifyHeadsImpl(LogicProgram& prg, PrgBody& target, AtomState& rs, bool strong); bool superfluousHead(const LogicProgram& prg, const PrgHead* head, PrgEdge it, const AtomState& rs) const; bool blockedHead(PrgEdge it, const AtomState& rs) const; void addHead(PrgEdge h); bool eraseHead(PrgEdge h); bool isSmallHead() const { return head_ != 3u; } byte_t* data() const { return const_cast(static_cast(data_)); } PrgEdge* smallHead() const { return const_cast(headData_.sm); } EdgeVec* largeHead() const { return headData_.ext; } SumData* sumData() const { return aggData().sum;} Agg& aggData() const { return *reinterpret_cast(data()); } Literal* goals_begin() { return type() == Body_t::Normal ? reinterpret_cast(data())->lits : aggData().lits; } Literal* goals_end() { return goals_begin() + size(); } uint32 size_ : 25; // |B| uint32 head_ : 2; // simple or extended head? uint32 type_ : 2; // body type uint32 sBody_ : 1; // simplify body? uint32 sHead_ : 1; // simplify head? uint32 freeze_ : 1; // keep body even if it does not occur in a rule? weight_t unsupp_; // <= 0 -> body is supported union Head { PrgEdge sm[2]; EdgeVec* ext; } headData_; // successors of this body byte_t data_[0]; // empty or one of Agg|Norm POTASSCO_WARNING_END_RELAXED }; //! The head of a disjunctive rule. class PrgDisj : public PrgHead { public: typedef const Var* atom_iterator; //! Constructor for disjunctions. static PrgDisj* create(uint32 id, const Potassco::AtomSpan& head); //! Destroys a disjunction created via create(). void destroy(); void detach(LogicProgram& prg); //! Number of atoms in disjunction. uint32 size() const { return data_; } atom_iterator begin() const { return atoms_; } atom_iterator end() const { return atoms_ + size(); } //! Propagates the assignment of an atom in this disjunction. bool propagateAssigned(LogicProgram& prg, PrgHead* at, EdgeType t); private: explicit PrgDisj(uint32 id, const Potassco::AtomSpan& head); ~PrgDisj(); POTASSCO_WARNING_BEGIN_RELAXED Var atoms_[0]; // atoms in disjunction POTASSCO_WARNING_END_RELAXED }; inline ValueRep getMergeValue(const PrgNode* lhs, const PrgNode* rhs) { return static_cast(std::min(static_cast(lhs->value()-1), static_cast(rhs->value()-1)) + 1); } template bool mergeValue(NT* lhs, NT* rhs){ ValueRep mv = getMergeValue(lhs, rhs); return (lhs->value() == mv || lhs->assignValue(mv)) && (rhs->value() == mv || rhs->assignValue(mv)); } //! A class for computing strongly connected components of the positive atom-body dependency graph. class SccChecker { public: SccChecker(LogicProgram& prg, AtomList& sccAtoms, uint32 startScc); uint32 sccs() const { return sccs_; } void visit(PrgBody* body) { visitDfs(body, PrgNode::Body); } void visit(PrgAtom* atom) { visitDfs(atom, PrgNode::Atom); } void visit(PrgDisj* disj) { visitDfs(disj, PrgNode::Disj); } private: struct Call { uintp node; uint32 min; uint32 next; }; typedef PodVector::type CallStack; typedef PodVector::type NodeStack; static uintp packNode(PrgNode* n, NodeType t) { return reinterpret_cast(n) + uintp(t); } static PrgNode* unpackNode(uintp n) { return reinterpret_cast(n & ~uintp(3u));} static bool isNode(uintp n, NodeType t) { return (n & 3u) == uintp(t); } bool doVisit(PrgNode* n, bool seen = true) const { return !n->ignoreScc() && n->relevant() && n->hasVar() && (!seen || !n->seen()); } void visitDfs(PrgNode* n, NodeType t); bool recurse(Call& c); bool onNode(PrgNode* n, NodeType t, Call& c, uint32 data); void addCall(PrgNode* n, NodeType t, uint32 next, uint32 min = 0) { Call c = {packNode(n, t), min, next}; callStack_.push_back(c); } CallStack callStack_; NodeStack nodeStack_; LogicProgram* prg_; AtomList* sccAtoms_; uint32 count_; uint32 sccs_; }; //! A set of ids of strongly connected components having at least one head-cycle. struct NonHcfSet : private PodVector::type { public: typedef PodVector::type base_type; typedef base_type::const_iterator const_iterator; using base_type::begin; using base_type::end; using base_type::size; NonHcfSet() : config(0) {} void add(uint32 scc) { iterator it = std::lower_bound(begin(), end(), scc); if (it == end() || *it != scc) { insert(it, scc); } } bool find(uint32 scc) const { const_iterator it = scc != PrgNode::noScc ? std::lower_bound(begin(), end(), scc) : end(); return it != end() && *it == scc; } Configuration* config; }; //@} } } #endif clingo-5.2.2/clasp/clasp/lookahead.h000066400000000000000000000224011320011352300172640ustar00rootroot00000000000000// // Copyright (c) 2009-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_LOOKAHEAD_H_INCLUDED #define CLASP_LOOKAHEAD_H_INCLUDED #ifdef _MSC_VER #pragma once #endif /*! * \file * \brief Defines lookahead related types. * * Lookahead can be used as a post propagator (e.g. failed-literal detection) and * optionally as an heuristic. */ #include #include namespace Clasp { /*! * \addtogroup propagator */ //@{ //! Type used to store lookahead-information for one variable. struct VarScore { VarScore() { clear(); } void clear() { std::memset(this, 0, sizeof(VarScore)); } //! Mark literal p as dependent. void setSeen( Literal p ) { seen_ |= uint32(p.sign()) + 1; } //! Is literal p dependent? bool seen(Literal p) const { return (seen_ & (uint32(p.sign())+1)) != 0; } //! Is this var dependent? bool seen() const { return seen_ != 0; } //! Mark literal p as tested during lookahead. void setTested( Literal p ) { tested_ |= uint32(p.sign()) + 1; } //! Was literal p tested during lookahead? bool tested(Literal p) const { return (tested_ & (uint32(p.sign())+1)) != 0; } //! Was some literal of this var tested? bool tested() const { return tested_ != 0; } //! Were both literals of this var tested? bool testedBoth() const { return tested_ == 3; } //! Sets the score for literal p to value and marks p as tested. void setScore(Literal p, LitVec::size_type value) { if (value > (1U<<14)-1) value = (1U<<14)-1; if (p.sign()) nVal_ = uint32(value); else pVal_ = uint32(value); setTested(p); } //! Sets the score of a dependent literal p to min(sc, current score). void setDepScore(Literal p, uint32 sc) { if (!seen(p) || score(p) > sc) { if (sc > (1U<<14)-1) sc = (1U<<14)-1; if (p.sign()) nVal_ = std::min(uint32(nVal_-(nVal_==0)), sc); else pVal_ = std::min(uint32(pVal_-(pVal_==0)), sc); } } //! Returns the score for literal p. uint32 score(Literal p) const { return p.sign() ? nVal_ : pVal_; } //! Returns the scores of the two literals of a variable. /*! * \param[out] mx The maximum score. * \param[out] mn The minimum score. */ void score(uint32& mx, uint32& mn) const { if (nVal_ > pVal_) { mx = nVal_; mn = pVal_; } else { mx = pVal_; mn = nVal_; } } //! Returns the sign of the literal that has the higher score. bool prefSign() const { return nVal_ > pVal_; } uint32 nVal() const { return nVal_; } uint32 pVal() const { return pVal_; } private: uint32 pVal_ : 14; uint32 nVal_ : 14; uint32 seen_ : 2; uint32 tested_: 2; }; //! A small helper class used to score the result of a lookahead operation. struct ScoreLook { enum Mode { score_max, score_max_min }; typedef PodVector::type VarScores; /**< A vector of variable-scores */ ScoreLook() : best(0), mode(score_max), addDeps(true), nant(false) {} bool validVar(Var v) const { return v < score.size(); } void scoreLits(const Solver& s, const Literal* b, const Literal *e); void clearDeps(); uint32 countNant(const Solver& s, const Literal* b, const Literal *e) const; bool greater(Var lhs, Var rhs)const; bool greaterMax(Var x, uint32 max) const { return score[x].nVal() > max || score[x].pVal() > max; } bool greaterMaxMin(Var lhs, uint32 max, uint32 min) const { uint32 lhsMin, lhsMax; score[lhs].score(lhsMax, lhsMin); return lhsMin > min || (lhsMin == min && lhsMax > max); } VarScores score; //!< score[v] stores lookahead score of v VarVec deps; //!< Tested vars and those that follow from them. VarType types; //!< Var types to consider. Var best; //!< Var with best score among those in deps. Mode mode; //!< Score mode to apply. bool addDeps;//!< Add/score dependent vars? bool nant; //!< Score only atoms in NegAnte(P)? }; class UnitHeuristic; //! Lookahead extends propagation with failed-literal detection. /*! * The class provides different kinds of one-step lookahead. * Atom- and body-lookahead are uniform lookahead types, where * either only atoms or bodies are tested. Hybrid-lookahead tests * both types of vars but each only in a single phase. I.e. atoms * are only tested negatively while bodies are tested positively. */ class Lookahead : public PostPropagator { public: //! Set of parameters to configure lookahead. struct Params { Params(VarType t = Var_t::Atom) : type(t), lim(0), topLevelImps(true), restrictNant(false) {} Params& lookahead(VarType t){ type = t; return *this; } Params& addImps(bool b) { topLevelImps = b; return *this; } Params& nant(bool b) { restrictNant = b; return *this; } Params& limit(uint32 x) { lim = x; return *this; } VarType type; uint32 lim; bool topLevelImps; bool restrictNant; }; static bool isType(uint32 t) { return t != 0 && t <= Var_t::Hybrid; } /*! * \param p Lookahead parameters to use. */ explicit Lookahead(const Params& p); ~Lookahead(); bool init(Solver& s); //! Clears the lookahead list. void clear(); //! Returns true if lookahead list is empty. bool empty() const { return head()->next == head_id; } //! Adds literal p to the lookahead list. void append(Literal p, bool testBoth); //! Executes a single-step lookahead on all vars in the loookahead list. bool propagateFixpoint(Solver& s, PostPropagator*); //! Returns PostPropagator::priority_reserved_look. uint32 priority() const; void destroy(Solver* s, bool detach); ScoreLook score; //!< State of last lookahead operation. //! Returns "best" literal w.r.t scoring of last lookahead or lit_true() if no such literal exists. Literal heuristic(Solver& s); void detach(Solver& s); bool hasLimit() const { return limit_ != 0; } protected: bool propagateLevel(Solver& s); // called by propagate void undoLevel(Solver& s); bool test(Solver& s, Literal p); private: typedef uint32 NodeId; enum { head_id = NodeId(0), undo_id = NodeId(1) }; struct LitNode { LitNode(Literal x) : lit(x), next(UINT32_MAX) {} Literal lit; NodeId next; }; typedef PodVector::type UndoStack; typedef PodVector::type LookList; typedef UnitHeuristic* HeuPtr; void splice(NodeId n); LitNode* node(NodeId n) { return &nodes_[n]; } LitNode* head() { return &nodes_[head_id]; } // head of circular candidate list LitNode* undo() { return &nodes_[undo_id]; } // head of undo list bool checkImps(Solver& s, Literal p); const LitNode* head() const { return &nodes_[head_id]; } LookList nodes_; // list of literals to test UndoStack saved_; // stack of undo lists LitVec imps_; // additional top-level implications NodeId last_; // last candidate in list; invariant: node(last_)->next == head_id; NodeId pos_; // current lookahead start position uint32 top_; // size of top-level uint32 limit_; // stop lookahead after this number of applications }; //@} //! Heuristic that uses the results of lookahead. /*! * \ingroup heuristic * The heuristic uses a Lookahead post propagator to select a literal with the highest score, * where the score is determined by counting assignments made during * failed-literal detection. For hybrid_lookahead, the heuristic selects the literal that * derived the most literals. On the other hand, for uniform_lookahead the heuristic is similar to * the smodels lookahead heuristic and selects the literal that maximizes the minimum. * \see Patrik Simons: "Extending and Implementing the Stable Model Semantics" for a * detailed description of the lookahead heuristic. * * \note The heuristic might itself apply some lookahead but only on variables that * did not fail in a previous call to Lookahead::propagateFixpoint(). I.e. if * priorities are correct for all post propagators in s, the lookahead operations can't fail. * * \note If no Lookahead post propagator exists in the solver, the heuristic selects the first free variable! */ class UnitHeuristic : public SelectFirst { public: UnitHeuristic(); //! Decorates the heuristic given in other with temporary lookahead. static UnitHeuristic* restricted(DecisionHeuristic* other); void endInit(Solver& /* s */); Literal doSelect(Solver& s); }; } #endif clingo-5.2.2/clasp/clasp/minimize_constraint.h000066400000000000000000000616711320011352300214360ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_MINIMIZE_CONSTRAINT_H_INCLUDED #define CLASP_MINIMIZE_CONSTRAINT_H_INCLUDED #ifdef _MSC_VER #pragma once #endif /*! * \file * \brief Types and functions for implementing minimization constraints. */ #include #include #include namespace Clasp { class MinimizeConstraint; class WeightConstraint; //! Supported minimization modes. /*! * \ingroup constraint * Defines the possible minimization modes used during solving. * If optimize is used, a valid candidate model is a solution that is * strictly smaller than all previous solutions. Otherwise, * solutions with costs no greater than a fixed bound are considered valid. */ struct MinimizeMode_t { enum Mode { ignore = 0, //!< Ignore optimize statements during solving. optimize = 1, //!< Optimize via a decreasing bound. enumerate = 2, //!< Enumerate models with cost less or equal to a fixed bound. enumOpt = 3, //!< Enumerate models with cost equal to optimum. }; }; typedef MinimizeMode_t::Mode MinimizeMode; //! A type holding data (possibly) shared between a set of minimize constraints. /*! * \ingroup shared_con */ class SharedMinimizeData { public: typedef SharedMinimizeData ThisType; //! A type to represent a weight at a certain level. /*! * Objects of this type are used to create sparse vectors of weights. E.g. * a weight vector (w1\@L1, w2\@L3, w3\@L5) is represented as \[\\\\], * where each \-tuple is an object of type LevelWeight. */ struct LevelWeight { LevelWeight(uint32 l, weight_t w) : level(l), next(0), weight(w) {} uint32 level : 31; //!< The level of this weight. uint32 next : 1; //!< Does this weight belong to a sparse vector of weights? weight_t weight; //!< The weight at this level. }; //! A type for holding sparse vectors of level weights of a multi-level constraint. typedef PodVector::type WeightVec; typedef PodVector::type PrioVec; explicit SharedMinimizeData(const SumVec& lhsAdjust, MinimizeMode m = MinimizeMode_t::optimize); //! Increases the reference count of this object. ThisType* share() { ++count_; return this; } //! Decreases the object's reference count and destroys it if reference count drops to 0. void release() { if (--count_ == 0) destroy(); } //! Number of minimize statements contained in this constraint. uint32 numRules() const{ return static_cast(adjust_.size()); } uint32 maxLevel() const{ return numRules()-1; } static wsum_t maxBound() { return INT64_MAX; } //! Returns the active minimization mode. MinimizeMode mode() const{ return mode_; } //! Returns true if optimization is active. bool optimize() const{ return optGen_ ? checkNext() : mode_ != MinimizeMode_t::enumerate; } //! Returns the lower bound of level x. wsum_t lower(uint32 x) const; //! Returns the upper bound of level x. wsum_t upper(uint32 x) const{ return upper()[x]; } const wsum_t* upper() const{ return &(up_ + (gCount_ & 1u))->front(); } //! Returns the sum of level x in the most recent model. wsum_t sum(uint32 x) const{ return sum()[x]; } const wsum_t* sum() const{ return (mode_ != MinimizeMode_t::enumerate) ? upper() : &up_[1][0]; } //! Returns the adjustment for level x. wsum_t adjust(uint32 x) const{ return adjust_[x]; } const wsum_t* adjust() const{ return &adjust_[0]; } //! Returns the current (ajusted and possibly tentative) optimum for level x. wsum_t optimum(uint32 x)const; //! Returns the highest level of the literal with the given index i. uint32 level(uint32 i) const{ return numRules() == 1 ? 0 : weights[lits[i].second].level; } //! Returns the most important weight of the literal with the given index i. weight_t weight(uint32 i) const{ return numRules() == 1 ? lits[i].second : weights[lits[i].second].weight; } uint32 generation() const{ return gCount_; } //! Returns whether minimization should search for solutions with current or next smaller upper bound. bool checkNext() const{ return mode() != MinimizeMode_t::enumerate && generation() != optGen_; } /*! * \name interface for optimization * If not otherwise specified, the following functions shall not be called concurrently. */ //@{ //! Sets the enumeration mode and (optionally) an initial bound. /*! * \note If m is MinimizeMode::enumerate, the caller should always * set a bound. Otherwise, *all* solutions are considered valid. */ bool setMode(MinimizeMode m, const wsum_t* bound = 0, uint32 boundSize = 0); bool setMode(MinimizeMode m, const SumVec& bound) { return setMode(m, bound.empty() ? 0 : &bound[0], (uint32)bound.size()); } void resetBounds(); //! Attaches a new minimize constraint to this data object. /*! * \param s Solver in which the new minimize constraint should apply. * \param params Parameters to pass to the optimization strategy. * \param addRef If true, the ref count of the shared object is increased. * Otherwise, the new minimize constraint inherits the reference to the shared object. */ MinimizeConstraint* attach(Solver& s, const OptParams& params, bool addRef = true); //! Makes opt the new (tentative) optimum. /*! * \pre opt is a pointer to an array of size numRules() */ const SumVec* setOptimum(const wsum_t* opt); //! Marks the current tentative optimum as the final optimum. /*! * \note Once a final optimum is set, further calls to setOptimum() * are ignored until resetBounds() is called. */ void markOptimal(); //! Sets the lower bound of level lev to low. void setLower(uint32 lev, wsum_t low); //! Sets the lower bound of level lev to the maximum of low and the existing value lower(lev). /*! * \note This function is thread-safe, i.e., can be called safely from multiple threads. */ wsum_t incLower(uint32 lev, wsum_t low); //@} /*! * \name Arithmetic functions on weights. */ //@{ //! Computes lhs += weight(lit). void add(wsum_t* lhs, const WeightLiteral& lit) const { if (weights.empty()) *lhs += lit.second; else add(lhs, &weights[lit.second]); } void add(wsum_t* lhs, const LevelWeight* w) const { do { lhs[w->level] += w->weight; } while (w++->next); } //! Computes lhs -= weight(lit). void sub(wsum_t* lhs, const WeightLiteral& lit, uint32& aLev) const { if (weights.empty()) *lhs -= lit.second; else sub(lhs, &weights[lit.second], aLev); } void sub(wsum_t* lhs, const LevelWeight* w, uint32& aLev) const; //! Returns (lhs + weight(lit)) > rhs bool imp(wsum_t* lhs, const WeightLiteral& lit, const wsum_t* rhs, uint32& lev) const { return weights.empty() ? (*lhs+lit.second) > *rhs : imp(lhs, &weights[lit.second], rhs, lev); } bool imp(wsum_t* lhs, const LevelWeight* w, const wsum_t* rhs, uint32& lev) const; //! Returns the weight of lit at level lev. weight_t weight(const WeightLiteral& lit, uint32 lev) const { if (numRules() == 1) { return lit.second * (lev == 0); } const LevelWeight* w = &weights[lit.second]; do { if (w->level == lev) return w->weight; } while (w++->next); return 0; } //@} private: typedef Clasp::Atomic_t::type CounterType; typedef Clasp::Atomic_t::type LowerType; SumVec adjust_; // initial bound adjustments SumVec up_[2]; // buffers for update via "double buffering" LowerType* lower_; // (unadjusted) lower bound of constraint MinimizeMode mode_; // how to compare assignments? CounterType count_; // number of refs to this object CounterType gCount_; // generation count - used when updating optimum uint32 optGen_; // generation of optimal bound public: WeightVec weights; // sparse vectors of weights - only used for multi-level constraints PrioVec prios; // (optional): maps levels to original priorities POTASSCO_WARNING_BEGIN_RELAXED WeightLiteral lits[0]; // (shared) literals - terminated with lit_true() POTASSCO_WARNING_END_RELAXED private: ~SharedMinimizeData(); void destroy() const; SharedMinimizeData(const SharedMinimizeData&); SharedMinimizeData& operator=(const SharedMinimizeData&); }; //! Helper class for creating minimize constraints. /*! * \ingroup constraint */ class MinimizeBuilder { public: typedef SharedMinimizeData SharedData; MinimizeBuilder(); MinimizeBuilder& add(weight_t prio, const WeightLitVec& lits); MinimizeBuilder& add(weight_t prio, WeightLiteral lit); MinimizeBuilder& add(weight_t prio, weight_t adjust); MinimizeBuilder& add(const SharedData& minCon); bool empty() const; //! Creates a new data object from previously added minimize literals. /*! * The function creates a new minimize data object from * the previously added literals to minimize. The returned * object can be used to attach one or more MinimizeConstraints. * \param ctx A ctx object to be associated with the new minmize constraint. * \return A data object representing previously added minimize statements or 0 if empty(). * \pre !ctx.frozen() * \post empty() */ SharedData* build(SharedContext& ctx); //! Discards any previously added minimize literals. void clear(); private: struct MLit { MLit(const WeightLiteral& wl, weight_t at) : lit(wl.first), prio(at), weight(wl.second) {} Literal lit; weight_t prio; weight_t weight; }; struct CmpPrio { bool operator()(const MLit& lhs, const MLit& rhs) const; }; struct CmpLit { bool operator()(const MLit& lhs, const MLit& rhs) const; }; struct CmpWeight{ CmpWeight(const SharedData::WeightVec* w) : weights(w) {} bool operator()(const MLit& lhs, const MLit& rhs) const; const SharedData::WeightVec* weights; }; typedef PodVector::type LitVec; void prepareLevels(const Solver& s, SumVec& adjustOut, WeightVec& priosOut); void mergeLevels(SumVec& adjust, SharedData::WeightVec& weightsOut); SharedData* createShared(SharedContext& ctx, const SumVec& adjust, const CmpWeight& cmp); LitVec lits_; }; //! Base class for implementing (mulit-level) minimize statements. /*! * \ingroup constraint * A solver contains at most one minimize constraint, but a minimize constraint * may represent several minimize statements. In that case, each minimize statement * has a unique level (starting at 0) and minimize statements with a lower level * have higher priority. Priorities are handled like in smodels, i.e. statements * with lower priority become relevant only if all statements with higher priority * currently have an optimal assignment. * * MinimizeConstraint supports two modes of operation: if mode is set to * optimize, solutions are considered optimal only if they are strictly smaller * than previous solutions. Otherwise, if mode is set to enumerate a * solution is valid if it is not greater than the initially set optimum. * Example: * m0: {a, b} * m1: {c, d} * All models: {a, c,...}, {a, d,...} {b, c,...}, {b, d,...} {a, b,...} * Mode = optimize: {a, c, ...} (m0 = 1, m1 = 1} * Mode = enumerate and initial opt=1,1: {a, c, ...}, {a, d,...}, {b, c,...}, {b, d,...} * */ class MinimizeConstraint : public Constraint { public: typedef SharedMinimizeData SharedData; typedef const SharedData* SharedDataP; //! Returns a pointer to the shared representation of this constraint. SharedDataP shared() const { return shared_; } //! Attaches this object to the given solver. virtual bool attach(Solver& s) = 0; //! Shall activate the minimize constraint by integrating bounds stored in the shared data object. virtual bool integrate(Solver& s) = 0; //! Shall relax this constraint (i.e. remove any bounds). /*! * If reset is true, shall also remove search-path related state. */ virtual bool relax(Solver& s, bool reset) = 0; //! Shall commit the model in s to the shared data object. /*! * The return value indicates whether the model is valid w.r.t the * costs stored in the shared data object. */ virtual bool handleModel(Solver& s) = 0; //! Shall handle the unsatisfiable path in s. virtual bool handleUnsat(Solver& s, bool upShared, LitVec& restore) = 0; virtual bool supportsSplitting() const { return true; } // base interface void destroy(Solver*, bool); Constraint* cloneAttach(Solver&) { return 0; } protected: MinimizeConstraint(SharedData* s); ~MinimizeConstraint(); void reportLower(Solver& s, uint32 level, wsum_t low) const; bool prepare(Solver& s, bool useTag); SharedData* shared_; // common shared data Literal tag_; // (optional) literal for tagging reasons }; //! Minimization via branch and bound. /*! * \ingroup constraint * The class supports both basic branch and bound as well as * hierarchical branch and bound (with or without varying step sizes). */ class DefaultMinimize : public MinimizeConstraint { public: explicit DefaultMinimize(SharedData* d, const OptParams& params); // base interface //! Attaches the constraint to the given solver. /*! * \pre s.decisionLevel() == 0 * \note If either MinimizeMode_t::enumOpt or hierarchical optimization * is active, s.sharedContext()->tagLiteral() shall be an unassigned literal. */ bool attach(Solver& s); bool integrate(Solver& s) { return integrateBound(s); } bool relax(Solver&, bool reset) { return relaxBound(reset); } bool handleModel(Solver& s) { commitUpperBound(s); return true; } bool handleUnsat(Solver& s, bool up, LitVec& out); // constraint interface PropResult propagate(Solver& s, Literal p, uint32& data); void undoLevel(Solver& s); void reason(Solver& s, Literal p, LitVec& lits); bool minimize(Solver& s, Literal p, CCMinRecursive* r); void destroy(Solver*, bool); // own interface bool active() const { return *opt() != SharedData::maxBound(); } //! Number of minimize statements contained in this constraint. uint32 numRules()const { return size_; } //! Tries to integrate the next tentative bound into this constraint. /*! * Starting from the current optimum stored in the shared data object, * the function tries to integrate the next candidate bound into * this constraint. * * \return The function returns true if integration succeeded. Otherwise * false is returned and s.hasConflict() is true. * * \note If integrateBound() failed, the bound of this constraint * is relaxed. The caller has to resolve the conflict first * and then integrateBound() shall be called again. * * \note The caller has to call s.propagate() to propagate any new information * from the new bound. * * \note If the tag literal (if any) is not true, the minimize constraint first assumes it. */ bool integrateBound(Solver& s); //! Sets the current local sum as the global optimum (upper bound). /*! * commitUpperBound() shall be called whenever the solver finds a model. * The current local sum is recorded as new optimum in the shared data object. * Once the local bound is committed, the function integrateBound() has to be * called in order to continue optimization. */ void commitUpperBound(const Solver& s); //! Sets the current local upper bound as the lower bound of this constraint. /*! * commitLowerBound() shall be called on unsat. The function stores * the local upper bound as new lower bound in this constraint. If upShared is true, * the lower bound is also copied to the shared data object. * * Once the local bound is committed, the function integrateBound() has to be * called in order to continue optimization. * \return false if search-space is exceeded w.r.t this constraint. */ bool commitLowerBound(Solver& s, bool upShared); //! Removes the local upper bound of this constraint and therefore disables it. /*! * If full is true, also removes search-path related state. */ bool relaxBound(bool full = false); bool more() const { return step_.lev != size_; } // FOR TESTING ONLY! wsum_t sum(uint32 i, bool adjust) const { return sum()[i] + (adjust ? shared_->adjust(i):0); } private: enum PropMode { propagate_new_sum, propagate_new_opt }; union UndoInfo; typedef const WeightLiteral* Iter; ~DefaultMinimize(); // bound operations wsum_t* opt() const { return bounds_; } wsum_t* sum() const { return bounds_ + size_; } wsum_t* temp()const { return bounds_ + (size_*2); } wsum_t* end() const { return bounds_ + (size_*3); } void assign(wsum_t* lhs, wsum_t* rhs) const; bool greater(wsum_t* lhs, wsum_t* rhs, uint32 len, uint32& aLev) const; // propagation & undo uint32 lastUndoLevel(const Solver& s) const; bool litSeen(uint32 i) const; bool propagateImpl(Solver& s, PropMode m); uint32 computeImplicationSet(const Solver& s, const WeightLiteral& it, uint32& undoPos); void pushUndo(Solver& s, uint32 litIdx); bool updateBounds(bool applyStep); // step wsum_t& stepLow() const { return *(end() + step_.lev); } void stepInit(uint32 n); wsum_t* bounds_; // [upper,sum,temp[,lower]] Iter pos_; // position of literal to look at next UndoInfo* undo_; // one "seen" flag for each literal + uint32 undoTop_; // undo stack holding assigned literals uint32 posTop_; // stack of saved "look at" positions const uint32 size_; // number of rules uint32 actLev_; // first level to look at when comparing bounds struct Step { // how to reduce next tentative bound uint32 size; // size of step uint32 lev : 30; // level on which step is applied uint32 type: 2; // type of step (one of OptParams::BBAlgo) } step_; }; //! Minimization via unsat cores. /*! * \ingroup constraint */ class UncoreMinimize : public MinimizeConstraint { public: // constraint interface PropResult propagate(Solver& s, Literal p, uint32& data); void reason(Solver& s, Literal p, LitVec& lits); void destroy(Solver*, bool); bool simplify(Solver& s, bool reinit = false); // base interface bool attach(Solver& s); bool integrate(Solver& s); bool relax(Solver&, bool reset); bool valid(Solver& s); bool handleModel(Solver& s); bool handleUnsat(Solver& s, bool up, LitVec& out); bool supportsSplitting() const { return false; } private: friend class SharedMinimizeData; explicit UncoreMinimize(SharedData* d, const OptParams& params); typedef DefaultMinimize* EnumPtr; struct LitData { LitData(weight_t w, bool as, uint32 c) : weight(w), coreId(c), assume((uint32)as), flag(0u) {} weight_t weight; uint32 coreId : 30; uint32 assume : 1; uint32 flag : 1; }; struct LitPair { LitPair(Literal p, uint32 dataId) : lit(p), id(dataId) {} Literal lit; uint32 id; }; struct Core { Core(WeightConstraint* c, weight_t b, weight_t w) : con(c), bound(b), weight(w) {} uint32 size() const; Literal at(uint32 i) const; Literal tag() const; WeightConstraint* con; weight_t bound; weight_t weight; }; struct WCTemp { typedef WeightLitVec WLitVec; typedef WeightLiteral* Ptr; void start(weight_t b){ lits.clear(); bound = b; } void add(Solver& s, Literal p); bool unsat() const { return bound > 0 && static_cast(bound) > static_cast(lits.size()); } uint32 size() const { return sizeVec(lits); } Ptr begin() { return size() ? &lits[0] : 0; } weight_t bound; WLitVec lits; }; typedef PodVector::type LitTable; typedef PodVector::type CoreTable; typedef PodVector::type ConTable; typedef PodVector::type LitSet; class Todo { public: typedef LitSet::const_iterator const_iterator; Todo() { clear(); } const_iterator begin() const { return lits_.begin(); } const_iterator end() const { return lits_.end(); } uint32 size() const { return sizeVec(lits_); } weight_t weight() const { return minW_; } bool shrink() const { return next_ != 0u; } void clear(bool resetShrink = true); void add(const LitPair& x, weight_t w); void terminate(); bool shrinkNext(UncoreMinimize& self, ValueRep result); void shrinkPush(UncoreMinimize& self, Solver& s); void shrinkReset(); private: bool subsetNext(UncoreMinimize& self, ValueRep result); LitSet lits_; weight_t minW_; // shrinking uint32 last_; uint32 next_; uint32 step_; LitSet core_; }; // literal and core management bool hasCore(const LitData& x) const { return x.coreId != 0; } bool flagged(uint32 id) const { return litData_[id-1].flag != 0u; } void setFlag(uint32 id, bool f) { litData_[id-1].flag = uint32(f); } LitData& getData(uint32 id) { return litData_[id-1];} Core& getCore(const LitData& x) { return open_[x.coreId-1]; } LitPair newAssumption(Literal p, weight_t w); Literal newLit(Solver& s); void releaseLits(); bool addCore(Solver& s, const LitPair* lits, uint32 size, weight_t w, bool updateLower); uint32 allocCore(WeightConstraint* con, weight_t bound, weight_t weight, bool open); bool closeCore(Solver& s, LitData& x, bool sat); bool addOll(Solver& s, const LitPair* lits, uint32 size, weight_t w); bool addOllCon(Solver& s, const WCTemp& wc, weight_t w); bool addK(Solver& s, uint32 K, const LitPair* lits, uint32 size, weight_t w); enum CompType { comp_disj = 0, comp_conj = 1 }; bool addPmr(Solver& s, const LitPair* lits, uint32 size, weight_t w); bool addPmrCon(CompType t, Solver& s, Literal head, Literal body1, Literal body2); bool addConstraint(Solver& s, WeightLiteral* lits, uint32 size, weight_t bound); bool addImplication(Solver& s, Literal a, Literal b, bool concise); // algorithm void init(); uint32 initRoot(Solver& s); bool initLevel(Solver& s); uint32 analyze(Solver& s); bool addNext(Solver& s); bool pushPath(Solver& s); bool popPath(Solver& s, uint32 dl); bool fixLit(Solver& s, Literal p); bool fixLevel(Solver& s); void detach(Solver* s, bool b); bool pushTrim(Solver& s); void resetTrim(Solver& s); bool push(Solver& s, Literal p, uint32 id); wsum_t* computeSum(const Solver& s) const; bool validLowerBound() const { wsum_t cmp = lower_ - upper_; return cmp < 0 || (cmp == 0 && level_ == shared_->maxLevel() && !shared_->checkNext()); } // data EnumPtr enum_; // for supporting (optimal) model enumeration in parallel mode wsum_t* sum_; // costs of active model LitTable litData_; // data for active literals (tag lits for cores + lits from active minimize) CoreTable open_; // open cores, i.e. relaxable and referenced by an assumption ConTable closed_; // closed cores represented as weight constraints LitSet assume_; // current set of assumptions Todo todo_; // core(s) not yet represented as constraint LitVec fix_; // set of fixed literals LitVec conflict_; // temporary: conflicting set of assumptions WCTemp temp_; // temporary: used for creating weight constraints wsum_t lower_; // lower bound of active level wsum_t upper_; // upper bound of active level uint32 auxInit_; // number of solver aux vars on attach uint32 auxAdd_; // number of aux vars added for cores uint32 gen_; // active generation uint32 level_ : 28;// active level uint32 next_ : 1;// update because of model uint32 disj_ : 1;// preprocessing active? uint32 path_ : 1;// push path? uint32 init_ : 1;// init constraint? weight_t actW_; // active weight limit (only weighted minimization with stratification) weight_t nextW_; // next weight limit (only weighted minimization with stratification) uint32 eRoot_; // saved root level of solver (initial gp) uint32 aTop_; // saved assumption level (added by us) uint32 freeOpen_; // head of open core free list OptParams options_; // active options }; } // end namespace Clasp #endif clingo-5.2.2/clasp/clasp/model_enumerators.h000066400000000000000000000125701320011352300210670ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //! \file //! \brief Model enumeration with minimization and projection. #ifndef CLASP_MODEL_ENUMERATORS_H #define CLASP_MODEL_ENUMERATORS_H #ifdef _MSC_VER #pragma once #endif #include #include namespace Clasp { //! Class for model enumeration with minimization and projection. /*! * This class implements algorithms for enumerating models with or without optimization * and/or projection. It supports two different algorithms (strategies). First, enumeration * via restricted backjumping, and second, enumeration via recording of solution nogoods. * * The first strategy, strategy_backtrack, maintains a special backtracking level to * suppress certain backjumps that could otherwise "re-open" search spaces already visited. * If projection is not active, no extra nogoods are created. * Otherwise, the number of additional solution nogoods is linear in the number of projection atoms. * * The second strategy, strategy_record, enumerates models by recording nogoods for found solutions. * In general, this strategy is exponential in space (bounded by the number of solutions). * On the other hand, if optimization is active, additional nogoods are not needed * because the optimization constraint already serves as solution nogood. * * There is also a third strategy, strategy_auto, provided for convenience. This * strategy automatically selects between strategy_backtrack and strategy_record * based on the problem at hand. It uses strategy_record, if one of the following holds: * - optimization is active, or * - only one model is requested, or * - both parallel search as well as projection are active * . * In all other cases, strategy_auto selects strategy_backtrack. * * \ingroup enumerator */ class ModelEnumerator : public Enumerator { public: //! Enumeration algorithms. enum Strategy { strategy_auto = 0, //!< Use strategy best suited to problem. strategy_backtrack = 1, //!< Use backtrack-based enumeration. strategy_record = 2 //!< Use nogood-based enumeration. }; //! Projective solution enumeration and options. enum ProjectOptions { project_enable_simple = 1, //!< Enable projective solution enumeration. project_use_heuristic = 2, //!< Use heuristic when selecting a literal from a projection nogood. project_save_progress = 4, //!< Enable progress saving after the first solution was found. project_enable_full = 6, //!< Enable projective solution enumeration with heuristic and progress saving. project_dom_lits = 8, //!< In strategy record, project only on true domain literals. }; /*! * \param st Enumeration strategy to apply. */ explicit ModelEnumerator(Strategy st = strategy_auto); ~ModelEnumerator(); //! Configure strategy. /*! * \param st Enumeration strategy to use. * \param projection The set of ProjectOptions to be applied or 0 to disable projective enumeration. * \param filter Ignore output predicates starting with filter in projective enumeration. */ void setStrategy(Strategy st = strategy_auto, uint32 projection = 0, char filter = '_'); bool projectionEnabled()const { return projectOpts() != 0; } bool domRec() const { return (projectOpts() & project_dom_lits) != 0; } Strategy strategy() const { return static_cast(opts_.algo); } bool project(Var v) const; protected: bool supportsRestarts() const { return optimize() || strategy() == strategy_record; } bool supportsParallel() const { return !projectionEnabled() || strategy() != strategy_backtrack; } bool supportsSplitting(const SharedContext& problem) const { return (strategy() == strategy_backtrack || !domRec()) && Enumerator::supportsSplitting(problem); } ConPtr doInit(SharedContext& ctx, SharedMinimizeData* m, int numModels); private: class ModelFinder; class BacktrackFinder; class RecordFinder; typedef PodVector::type WordVec; void initProjection(SharedContext& ctx); void addProject(SharedContext& ctx, Var v); uint32 projectOpts() const { return opts_.proj; } bool trivial() const { return trivial_; } WordVec project_; char filter_; struct Options { uint8 proj : 4; uint8 algo : 2; } opts_, saved_; bool trivial_; }; } #endif clingo-5.2.2/clasp/clasp/mt/000077500000000000000000000000001320011352300156055ustar00rootroot00000000000000clingo-5.2.2/clasp/clasp/mt/mutex.h000066400000000000000000000036221320011352300171230ustar00rootroot00000000000000// // Copyright (c) 2012-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_UTIL_MUTEX_H_INCLUDED #define CLASP_UTIL_MUTEX_H_INCLUDED #include #include namespace Clasp { namespace mt { using std::mutex; using std::lock_guard; using std::unique_lock; using std::swap; using std::defer_lock_t; struct condition_variable : private std::condition_variable { typedef std::condition_variable base_type; using base_type::notify_one; using base_type::notify_all; using base_type::wait; using base_type::native_handle; inline bool wait_for(unique_lock& lock, double timeInSecs) { return base_type::wait_for(lock, std::chrono::duration_cast(std::chrono::duration(timeInSecs))) == std::cv_status::no_timeout; } }; }} #endif clingo-5.2.2/clasp/clasp/mt/parallel_solve.h000066400000000000000000000350021320011352300207620ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_PARALLEL_SOLVE_H_INCLUDED #define CLASP_PARALLEL_SOLVE_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #if !CLASP_HAS_THREADS #error Thread support required for parallel solving #endif #include #include #include #include #include #include /*! * \file * \brief Defines classes controlling multi-threaded parallel solving. */ namespace Clasp { //! Namespace for types and functions needed for implementing multi-threaded parallel solving. namespace mt { /** * \defgroup mt Multi-threading * \brief Parallel solving and related classes. * \ingroup enumerator */ //@{ class ParallelHandler; class ParallelSolve; //! Options for controlling parallel solving. struct ParallelSolveOptions : BasicSolveOptions { //! Nogood distribution options. struct Distribution : Distributor::Policy { enum Mode { mode_global = 0, mode_local = 1 }; Distribution(Mode m = mode_global) : Distributor::Policy(), mode(m) {} Distributor::Policy& policy() { return *this; } uint32 mode; }; ParallelSolveOptions() {} //! Algorithm options. struct Algorithm { //! Possible search strategies. enum SearchMode { mode_split = 0, mode_compete = 1 }; Algorithm() : threads(1), mode(mode_compete) {} uint32 threads; SearchMode mode; }; //! Nogood integration options. struct Integration { static const uint32 GRACE_MAX = (1u<<28)-1; Integration() : grace(1024), filter(filter_gp), topo(topo_all) {} enum Filter { filter_no = 0, filter_gp = 1, filter_sat = 2, filter_heuristic = 3 }; enum Topology { topo_all = 0, topo_ring = 1, topo_cube = 2, topo_cubex = 3 }; uint32 grace : 28; /**< Lower bound on number of shared nogoods to keep. */ uint32 filter: 2; /**< Filter for integrating shared nogoods (one of Filter). */ uint32 topo : 2; /**< Integration topology */ }; //! Global restart options. struct GRestarts { GRestarts():maxR(0) {} uint32 maxR; ScheduleStrategy sched; }; Integration integrate; //!< Nogood integration options to apply during search. Distribution distribute;//!< Nogood distribution options to apply during search. GRestarts restarts; //!< Global restart strategy to apply during search. Algorithm algorithm; //!< Parallel algorithm to use. //! Allocates a new solve object. SolveAlgorithm* createSolveObject() const; //! Returns the number of threads that can run concurrently on the current hardware. static uint32 recommendedSolvers() { return Clasp::mt::thread::hardware_concurrency(); } //! Returns number of maximal number of supported threads. static uint32 supportedSolvers() { return 64; } //! Returns the peers of the solver with the given id assuming the given topology. static uint64 initPeerMask(uint32 sId, Integration::Topology topo, uint32 numThreads); uint32 numSolver() const { return algorithm.threads; } void setSolvers(uint32 i) { algorithm.threads = std::max(uint32(1), i); } bool defaultPortfolio() const { return algorithm.mode == Algorithm::mode_compete; } }; //! A parallel algorithm for multi-threaded solving with and without search-space splitting. /*! * The class adapts clasp's basic solve algorithm * to a parallel solve algorithm that solves * a problem using a given number of threads. * It supports guiding path based solving, portfolio based solving, as well * as a combination of these two approaches. */ class ParallelSolve : public SolveAlgorithm { public: explicit ParallelSolve(const ParallelSolveOptions& opts); ~ParallelSolve(); // base interface virtual bool interrupted() const; virtual void resetSolve(); virtual void enableInterrupts(); // own interface //! Returns the number of active threads. uint32 numThreads() const; bool integrateUseHeuristic() const { return test_bit(intFlags_, 31); } uint32 integrateGrace() const { return intGrace_; } uint32 integrateFlags() const { return intFlags_; } uint64 hasErrors() const; //! Requests a global restart. void requestRestart(); bool handleMessages(Solver& s); bool integrateModels(Solver& s, uint32& mCount); void pushWork(LitVec* gp); bool commitModel(Solver& s); bool commitUnsat(Solver& s); enum GpType { gp_none = 0, gp_split = 1, gp_fixed = 2 }; private: ParallelSolve(const ParallelSolve&); ParallelSolve& operator=(const ParallelSolve&); typedef SingleOwnerPtr PathPtr; enum ErrorCode { LogicError = 1, RuntimeError = 2, OutOfMemory = 3, UnknownError = 4 }; enum { masterId = 0 }; // ------------------------------------------------------------------------------------------- // Thread setup struct EntryPoint; void destroyThread(uint32 id); void allocThread(uint32 id, Solver& s); void joinThreads(); // ------------------------------------------------------------------------------------------- // Algorithm steps void setIntegrate(uint32 grace, uint8 filter); void setRestarts(uint32 maxR, const ScheduleStrategy& rs); bool beginSolve(SharedContext& ctx, const LitVec& assume); bool doSolve(SharedContext& ctx, const LitVec& assume); void doStart(SharedContext& ctx, const LitVec& assume); int doNext(int last); void doStop(); bool doInterrupt(); void solveParallel(uint32 id); void initQueue(); bool requestWork(Solver& s, PathPtr& out); void terminate(Solver& s, bool complete); bool waitOnSync(Solver& s); void exception(uint32 id, PathPtr& path, ErrorCode e, const char* what); void reportProgress(const Event& ev) const; void reportProgress(const Solver& s, const char* msg) const; // ------------------------------------------------------------------------------------------- typedef ParallelSolveOptions::Distribution Distribution; struct SharedData; // SHARED DATA SharedData* shared_; // Shared control data ParallelHandler** thread_; // Thread-locl control data // READ ONLY Distribution distribution_; // distribution options uint32 maxRestarts_; // disable global restarts once reached uint32 intGrace_ : 30;// grace period for clauses to integrate uint32 intTopo_ : 2;// integration topology uint32 intFlags_; // bitset controlling clause integration bool modeSplit_; }; //! An event type for debugging messages sent between threads. struct MessageEvent : SolveEvent { enum Action { sent, received, completed }; MessageEvent(const Solver& s, const char* message, Action a, double t = 0.0) : SolveEvent(s, verbosity_high), msg(message), time(t) { op = (uint32)a; } const char* msg; // name of message double time; // only for action completed }; //! A per-solver (i.e. thread) class that implements message handling and knowledge integration. /*! * The class adds itself as a post propagator to the given solver. During propagation * it checks for new messages and lemmas to integrate. */ class ParallelHandler : public MessageHandler { public: typedef ParallelSolve::GpType GpType; //! Creates a new parallel handler to be used in the given solve group. /*! * \param ctrl The object controlling the parallel solve operation. * \param s The solver that is to be controlled by this object. */ explicit ParallelHandler(ParallelSolve& ctrl, Solver& s); ~ParallelHandler(); //! Attaches the object's solver to ctx and adds this object as a post propagator. bool attach(SharedContext& ctx); //! Removes this object from the list of post propagators of its solver and detaches the solver from ctx. void detach(SharedContext& ctx, bool fastExit); bool setError(int e); int error() const { return (int)error_; } void setWinner() { win_ = 1; } bool winner() const { return win_ != 0; } void setThread(Clasp::mt::thread& x) { assert(!joinable()); x.swap(thread_); assert(joinable()); } //! True if *this has an associated thread of execution, false otherwise. bool joinable() const { return thread_.joinable(); } //! Waits for the thread of execution associated with *this to finish. int join() { if (joinable()) { thread_.join(); } return error(); } // overridden methods //! Integrates new information. bool propagateFixpoint(Solver& s, PostPropagator*); bool handleMessages() { return ctrl_->handleMessages(solver()); } void reset() { up_ = 1; } bool simplify(Solver& s, bool re); //! Checks whether new information has invalidated current model. bool isModel(Solver& s); // own interface // TODO: make functions virtual once necessary //! Returns true if handler's guiding path is disjoint from all others. bool disjointPath() const { return gp_.type == ParallelSolve::gp_split; } //! Returns true if handler has a guiding path. bool hasPath() const { return gp_.type != ParallelSolve::gp_none; } void setGpType(GpType t) { gp_.type = t; } //! Entry point for solving the given guiding path. /*! * \param solve The object used for solving. * \param type The guiding path's type. * \param restart Request restart after restart number of conflicts. */ ValueRep solveGP(BasicSolve& solve, GpType type, uint64 restart); /*! * \name Message handlers * \note * Message handlers are intended as callbacks for ParallelSolve::handleMessages(). * They shall not change the assignment of the solver object. */ //@{ //! Algorithm is about to terminate. /*! * Removes this object from the solver's list of post propagators. */ void handleTerminateMessage(); //! Request for split. /*! * Splits off a new guiding path and adds it to the control object. * \pre The guiding path of this object is "splittable" */ void handleSplitMessage(); //! Request for (global) restart. /*! * \return true if restart is valid, else false. */ bool handleRestartMessage(); Solver& solver() { return *solver_; } //@} private: void add(ClauseHead* h); void clearDB(Solver* s); bool integrate(Solver& s); typedef PodVector::type ClauseDB; typedef SharedLiterals** RecBuffer; struct GP { uint64 restart; // don't give up before restart number of conflicts uint32 modCount; // integration counter for synchronizing models GpType type; // type of gp void reset(uint64 r = UINT64_MAX, GpType t = ParallelSolve::gp_none) { restart = r; modCount = 0; type = t; } }; enum { RECEIVE_BUFFER_SIZE = 32 }; Clasp::mt::thread thread_; // active thread or empty for master GP gp_; // active guiding path ParallelSolve* ctrl_; // message source Solver* solver_; // associated solver RecBuffer received_; // received clauses not yet integrated ClauseDB integrated_; // integrated clauses uint32 recEnd_; // where to put next received clause uint32 intEnd_; // where to put next clause uint32 error_:28; // error code or 0 if ok uint32 win_ : 1; // 1 if thread was the first to terminate the search uint32 up_ : 1; // 1 if next propagate should check for new lemmas/models uint32 act_ : 1; // 1 if gp is active uint32 lbd_ : 1; // 1 if integrate should compute lbds }; //! A class that uses a global list to exchange nogoods between threads. class GlobalDistribution : public Distributor { public: explicit GlobalDistribution(const Policy& p, uint32 maxShare, uint32 topo); ~GlobalDistribution(); uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut); void publish(const Solver& source, SharedLiterals* n); private: void release(); struct ClausePair { ClausePair(uint32 sId = UINT32_MAX, SharedLiterals* x = 0) : sender(sId), lits(x) {} uint32 sender; SharedLiterals* lits; }; class Queue : public MultiQueue { public: typedef MultiQueue base_type; using base_type::publish; Queue(uint32 m) : base_type(m) {} }; struct ThreadInfo { uint64 peerMask; union { Queue::ThreadId id; uint64 rep; }; char pad[64 - (sizeof(uint64)*2)]; }; Queue::ThreadId& getThreadId(uint32 sId) const { return threadId_[sId].id; } uint64 getPeerMask(uint32 sId) const { return threadId_[sId].peerMask; } Queue* queue_; ThreadInfo* threadId_; }; //! A class that uses thread-local lists to exchange nogoods between threads. class LocalDistribution : public Distributor { public: explicit LocalDistribution(const Policy& p, uint32 maxShare, uint32 topo); ~LocalDistribution(); uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut); void publish(const Solver& source, SharedLiterals* n); private: typedef Detail::RawStack RawStack; typedef MPSCPtrQueue::Node QNode; enum { BLOCK_CAP = 128 }; QNode* allocNode(uint32 tId, SharedLiterals* clause); void freeNode(uint32 tId, QNode* n) const; struct ThreadData { MPSCPtrQueue received; // queue holding received clauses uint64 peers; // set of peers from which this thread receives clauses QNode sentinal; // sentinal node for simplifying queue impl QNode* free; // local free list - only accessed by this thread }** thread_; // one entry for each thread RawStack blocks_; // allocated node blocks uint32 numThread_; // number of threads, i.e. size of array thread_ }; //@} } } #endif clingo-5.2.2/clasp/clasp/mt/thread.h000066400000000000000000000026051320011352300172300ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_UTIL_THREAD_H_INCLUDED #define CLASP_UTIL_THREAD_H_INCLUDED #include namespace Clasp { namespace mt { using std::thread; namespace this_thread { using std::this_thread::yield; } }} #endif clingo-5.2.2/clasp/clasp/parser.h000066400000000000000000000152601320011352300166360ustar00rootroot00000000000000// // Copyright (c) 2014-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_PARSER_H_INCLUDED #define CLASP_PARSER_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include #include #include /*! * \file * \brief Defines parsers for supported input formats. */ namespace Clasp { ///////////////////////////////////////////////////////////////////////////////////////// // PARSING BASE ///////////////////////////////////////////////////////////////////////////////////////// /*! * \addtogroup problem */ //@{ //! Auto-detect type of program given in prg. ProblemType detectProblemType(std::istream& prg); //! Parse additional information in symbol table/comments. struct ParserOptions { //! Supported parser extensions. enum Extension { parse_heuristic = 1u, //!< Parse heuristic info in smodels, dimacs, and pb format. parse_acyc_edge = 2u, //!< Parse acyc info in smodels, dimacs, and pb format. parse_minimize = 4u, //!< Parse cost function in dimacs format. parse_project = 8u, //!< Parse project directive in dimacs and pb format. parse_assume = 16u,//!< Parse assumption directive in dimacs and pb format. parse_output = 32u,//!< Parse output directive in dimacs and pb format. parse_full = 63u, parse_maxsat = 128u//!< Parse dimacs as MaxSAT problem }; ParserOptions() : set(0) {} ParserOptions& enableHeuristic() { set |= parse_heuristic; return *this; } ParserOptions& enableAcycEdges() { set |= parse_acyc_edge; return *this; } ParserOptions& enableMinimize() { set |= parse_minimize; return *this; } ParserOptions& enableProject() { set |= parse_project; return *this; } ParserOptions& enableAssume() { set |= parse_assume; return *this; } ParserOptions& enableOutput() { set |= parse_output; return *this; } ParserOptions& assign(uint8 f, bool b) { if (b) { set |= f; } else { set &= ~f; } return *this; } bool isEnabled(Extension e) const { return (set & static_cast(e)) != 0u; } bool anyOf(uint8 f) const { return (set & f) != 0u; } uint8 set; }; //! Base class for parsers. class ProgramParser { public: typedef Potassco::ProgramReader StrategyType; static const Var VAR_MAX = varMax - 1; ProgramParser(); virtual ~ProgramParser(); bool accept(std::istream& str, const ParserOptions& o = ParserOptions()); bool incremental() const; bool isOpen() const; bool parse(); bool more(); void reset(); private: virtual StrategyType* doAccept(std::istream& str, const ParserOptions& o) = 0; StrategyType* strat_; }; //! Parser for logic programs in smodels-internal or aspif format. class AspParser : public ProgramParser { public: static bool accept(char c); explicit AspParser(Asp::LogicProgram& prg); ~AspParser(); enum Format { format_smodels = -1, format_aspif = 1 }; static void write(Asp::LogicProgram& prg, std::ostream& os); static void write(Asp::LogicProgram& prg, std::ostream& os, Format f); protected: virtual StrategyType* doAccept(std::istream& str, const ParserOptions& o); private: struct SmAdapter; Asp::LogicProgram* lp_; StrategyType* in_; Potassco::AbstractProgram* out_; }; ///////////////////////////////////////////////////////////////////////////////////////// // SAT parsing ///////////////////////////////////////////////////////////////////////////////////////// //! Base class for dimacs and opb parser. class SatReader : public Potassco::ProgramReader { public: SatReader(); ParserOptions options; protected: bool skipLines(char start); void parseExt(const char* pre, uint32 maxVar, SharedContext& ctx); // ::= { } void parseProject(uint32 maxVar, SharedContext& ctx); // ::= { } void parseAssume(uint32 maxVar); // ::= void parseHeuristic(uint32 maxVar, SharedContext& ctx); // ::= "range" // | void parseOutput(uint32 maxVar, SharedContext& ctx); void parseGraph(uint32 maxVar, const char* pre, ExtDepGraph& graph); virtual void addObjective(const WeightLitVec& vec) = 0; virtual void addAssumption(Literal x) = 0; private: Literal matchLit(Var max); }; //! Parser for (extended) dimacs format. class DimacsReader : public SatReader { public: static bool accept(char c) { return c == 'c' || c == 'p'; } DimacsReader(SatBuilder&); protected: virtual bool doAttach(bool& inc); virtual bool doParse(); virtual void addObjective(const WeightLitVec& vec); virtual void addAssumption(Literal x); private: SatBuilder* program_; Var numVar_; bool wcnf_; }; //! Parser for opb format. class OpbReader : public SatReader { public: OpbReader(PBBuilder&); static bool accept(char c) { return c == '*'; } protected: virtual bool doAttach(bool& inc); virtual bool doParse(); virtual void addObjective(const WeightLitVec& vec); virtual void addAssumption(Literal x); void parseOptObjective(); void parseConstraint(); void parseSum(); void parseTerm(); private: PBBuilder* program_; weight_t minCost_; weight_t maxCost_; struct Temp { WeightLitVec lits; LitVec term; weight_t bound; bool eq; } active_; }; //! Parser for SAT or PB problems. class SatParser : public ProgramParser { public: explicit SatParser(SatBuilder& prg); explicit SatParser(PBBuilder& prg); ~SatParser(); protected: virtual StrategyType* doAccept(std::istream& str, const ParserOptions& o); private: SatReader* reader_; }; //@} } #endif clingo-5.2.2/clasp/clasp/pod_vector.h000066400000000000000000000070501320011352300175040ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_POD_VECTOR_H_INCLUDED #define CLASP_POD_VECTOR_H_INCLUDED #include #include #include #include namespace Clasp { #if CLASP_USE_STD_VECTOR template struct PodVector { typedef std::vector type; static void destruct(type& t) {t.clear();} }; #else //! Type selector for a vector type optimized for storing POD-types. template struct PodVector { typedef bk_lib::pod_vector type; static void destruct(type& t) { for (typename type::size_type i = 0, end = t.size(); i != end; ++i) { t[i].~Type(); } t.clear(); } }; #endif inline uint32 toU32(std::size_t x) { assert(sizeof(std::size_t) <= sizeof(uint32) || x <= static_cast(UINT32_MAX)); return static_cast(x); } template inline uint32 sizeVec(const T& c) { return toU32(c.size()); } template inline void releaseVec(T& t) { T().swap(t); } template inline void shrinkVecTo(T& t, typename T::size_type j) { t.erase(t.begin()+j, t.end()); } template inline void growVecTo(T& vec, typename T::size_type j, const typename T::value_type& val = typename T::value_type()) { if (vec.size() < j) { if (vec.capacity() < j) { vec.reserve(j + j / 2); } vec.resize(j, val); } } template void moveDown(T& t, typename T::size_type from, typename T::size_type to) { for (typename T::size_type end = t.size(); from != end;) { t[to++] = t[from++]; } shrinkVecTo(t, to); } //! A simple vector-based fifo queue for storing POD-types. template struct PodQueue { typedef typename PodVector::type vec_type; typedef typename vec_type::size_type size_type; PodQueue() : qFront(0) {} bool empty() const { return qFront == vec.size(); } size_type size() const { return vec.size() - qFront; } const T& front() const { return vec[qFront]; } const T& back() const { return vec.back(); } T& front() { return vec[qFront]; } T& back() { return vec.back(); } void push(const T& x){ vec.push_back(x); } void pop() { ++qFront; } T pop_ret() { return vec[qFront++]; } void clear() { vec.clear(); qFront = 0; } void rewind() { qFront = 0; } vec_type vec; // the underlying vector holding the items size_type qFront; // front position }; } #endif clingo-5.2.2/clasp/clasp/program_builder.h000066400000000000000000000234251320011352300205210ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_PROGRAM_BUILDER_H_INCLUDED #define CLASP_PROGRAM_BUILDER_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include #include POTASSCO_EXT_INCLUDE(unordered_map) #include namespace Clasp { /** * \file * \defgroup problem Input * \brief Classes and functions for defining input programs. */ //@{ //! Interface for defining an input program. class ProgramBuilder { public: typedef SharedMinimizeData SharedMinimize; typedef SingleOwnerPtr MinPtr; ProgramBuilder(); virtual ~ProgramBuilder(); //! Starts the definition of a program. /*! * This function shall be called exactly once before a new program is defined. * It discards any previously added program. * * \param ctx The context object in which the program should be stored. */ bool startProgram(SharedContext& ctx); //! Parses the given stream as a program of type() and adds it to this object. bool parseProgram(std::istream& prg); //! Unfreezes a currently frozen program. bool updateProgram(); //! Loads the program into the shared context passed to startProgram(). bool endProgram(); //! Returns any assumptions that shall hold during solving. /*! * \pre frozen() */ void getAssumptions(LitVec& out) const; //! Returns bounds that shall hold during minimization. void getWeakBounds(SumVec& out) const; //! Returns the type of program that is created by this builder. int type() const { return doType(); } //! Returns true if the program is currently frozen. bool frozen() const { return frozen_; } //! Returns true if the program is not conflicting. virtual bool ok() const; //! Returns the stored context object. SharedContext* ctx() const { return ctx_; } //! Returns a parser for this type of program associated with this object. ProgramParser& parser(); protected: void addMinLit(weight_t prio, WeightLiteral x); void setFrozen(bool frozen) { frozen_ = frozen; } void setCtx(SharedContext* x){ ctx_ = x; } void markOutputVariables() const; private: typedef SingleOwnerPtr MinBuildPtr; typedef SingleOwnerPtr ParserPtr; ProgramBuilder(const ProgramBuilder&); ProgramBuilder& operator=(ProgramBuilder&); virtual bool doStartProgram() = 0; virtual bool doUpdateProgram() = 0; virtual bool doEndProgram() = 0; virtual void doGetWeakBounds(SumVec& out) const; virtual void doGetAssumptions(LitVec& out) const = 0; virtual int doType() const = 0; virtual ProgramParser* doCreateParser() = 0; SharedContext* ctx_; ParserPtr parser_; bool frozen_; }; //! A class for defining a SAT-problem in CNF. class SatBuilder : public ProgramBuilder { public: explicit SatBuilder(); // program definition //! Creates necessary variables and prepares the problem. /*! * \param numVars Number of variables to create. * \param hardClauseWeight Weight identifying hard clauses (0 means no weight). * Clauses added with a weight != hardClauseWeight are * considered soft clauses (see addClause()). * \param clauseHint A hint on how many clauses will be added. */ void prepareProblem(uint32 numVars, wsum_t hardClauseWeight = 0, uint32 clauseHint = 100); //! Returns the number of variables in the problem. Var numVars() const { return vars_; } //! Adds the given clause to the problem. /*! * The SatBuilder supports the creation of (weighted) MaxSAT problems * via the creation of "soft clauses". For this, clauses * added to this object have an associated weight cw. If cw * does not equal hardClauseWeight (typically 0), the clause is a * soft clause and not satisfying it results in a penalty of cw. * * \pre v <= numVars(), for all variables v occuring in clause. * \pre cw >= 0. * \param clause The clause to add. * \param cw The weight associated with the clause. */ bool addClause(LitVec& clause, wsum_t cw = 0); //! Adds the given PB-constraint (sum(lits) >= bound) to the problem. bool addConstraint(WeightLitVec& lits, weight_t bound); //! Adds min as an objective function to the problem. bool addObjective(const WeightLitVec& min); //! Adds v to the set of projection vars. void addProject(Var v); //! Adds x to the set of initial assumptions. void addAssumption(Literal x); private: typedef PodVector::type VarState; bool doStartProgram(); ProgramParser* doCreateParser(); int doType() const { return Problem_t::Sat; } bool doUpdateProgram() { return !frozen(); } void doGetAssumptions(LitVec& a) const { a.insert(a.end(), assume_.begin(), assume_.end()); } bool doEndProgram(); bool satisfied(LitVec& clause); bool markAssigned(); void markLit(Literal x) { varState_[x.var()] |= 1 + x.sign(); } VarState varState_; LitVec softClauses_; LitVec assume_; wsum_t hardWeight_; Var vars_; uint32 pos_; }; //! A class for defining a PB-problem. class PBBuilder : public ProgramBuilder { public: PBBuilder(); // program definition //! Creates necessary variables and prepares the problem. /*! * \param numVars Number of problem variables to create. * \param maxProduct Max number of products in the problem. * \param maxSoft Max number of soft constraints in the problem. * \param constraintHint A hint on how many clauses will be added. */ void prepareProblem(uint32 numVars, uint32 maxProduct, uint32 maxSoft, uint32 constraintHint = 100); //! Returns the number of variables in the problem. uint32 numVars() const { return auxVar_ - 1; } //! Adds the given PB-constraint to the problem. /*! * A PB-constraint consists of a list of weighted Boolean literals (lhs), * a comparison operator (either >= or =), and an integer bound (rhs). * * \pre v <= numVars(), for all variables v occuring in lits. * \pre bound >= 0 && cw >= 0. * * \param lits The lhs of the PB-constraint. * \param bound The rhs of the PB-constraint. * \param eq If true, use '=' instead of '>=' as comparison operator. * \param cw If > 0, treat constraint as soft constraint with weight cw. */ bool addConstraint(WeightLitVec& lits, weight_t bound, bool eq = false, weight_t cw = 0); //! Adds the given product to the problem. /*! * The function creates the equality x == l1 && ... && ln, where x is a new * literal and each li is a literal in lits. * \pre The number of products added so far is < maxProduct that was given in prepareProblem(). */ Literal addProduct(LitVec& lits); //! Adds min as an objective function to the problem. bool addObjective(const WeightLitVec& min); //! Adds v to the set of projection vars. void addProject(Var v); //! Adds x to the set of initial assumptions. void addAssumption(Literal x); //! Only allow solutions where the sum of violated soft constraint is less than bound. bool setSoftBound(wsum_t bound); private: struct PKey { LitVec lits; std::size_t operator()(const PKey& k) const { return k.lits[0].rep(); } bool operator()(const PKey& lhs, const PKey& rhs) const { return lhs.lits == rhs.lits; } }; typedef POTASSCO_EXT_NS::unordered_map ProductIndex; bool doStartProgram(); void doGetWeakBounds(SumVec& out) const; int doType() const { return Problem_t::Pb; } bool doUpdateProgram() { return !frozen(); } void doGetAssumptions(LitVec& a) const { a.insert(a.end(), assume_.begin(), assume_.end()); } ProgramParser* doCreateParser(); bool doEndProgram(); bool productSubsumed(LitVec& lits, PKey& prod); void addProductConstraints(Literal eqLit, LitVec& lits); Var getAuxVar(); ProductIndex products_; PKey prod_; LitVec assume_; uint32 auxVar_; uint32 endVar_; wsum_t soft_; }; //! Adapts a Sat or PB builder to the Potassco::AbstractProgram interface. class BasicProgramAdapter : public Potassco::AbstractProgram { public: BasicProgramAdapter(ProgramBuilder& prg); void initProgram(bool inc); void beginStep(); void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body); void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body); void minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits); protected: ProgramBuilder* prg_; LitVec clause_; WeightLitVec constraint_; bool inc_; }; } #endif clingo-5.2.2/clasp/clasp/satelite.h000066400000000000000000000164101320011352300171520ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //! \file //! \brief Types and functions for SAT-based preprocessing. #ifndef CLASP_SATELITE_H_INCLUDED #define CLASP_SATELITE_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include namespace Clasp { //! SatElite preprocessor for clauses. /*! * \ingroup shared * The preprocessor implements subsumption, self-subsumption, variable elimination, * and (optionally) blocked clause elimination. * \see * - Niklas Eén, Armin Biere: "Effective Preprocessing in SAT through Variable and Clause Elimination" * - Matti Järvisalo, Armin Biere, Marijn Heule: "Blocked Clause Elimination" * - Parts of the SatElite preprocessor are adapted from MiniSAT 2.0 beta * available under the MIT licence from http://minisat.se/MiniSat.html * . */ class SatElite : public Clasp::SatPreprocessor { public: SatElite(); ~SatElite(); Clasp::SatPreprocessor* clone(); //! Event type for providing information on preprocessing progress. struct Progress : public Event_t { enum EventOp { event_algorithm = '*', event_bce = 'B', event_var_elim = 'E', event_subsumption = 'S', }; Progress(SatElite* p, EventOp o, uint32 i, uint32 m) : Event_t(Event::subsystem_prepare, Event::verbosity_high), self(p), cur(i), max(m) { op = (uint32)o; } SatElite* self; uint32 cur; uint32 max; }; protected: bool initPreprocess(Options& opts); void reportProgress(Progress::EventOp, uint32 curr, uint32 max); bool doPreprocess(); void doExtendModel(ValueVec& m, LitVec& open); void doCleanUp(); private: typedef PodVector::type TouchedList; typedef bk_lib::left_right_sequence ClWList; typedef ClWList::left_iterator ClIter; typedef ClWList::right_iterator WIter; typedef std::pair ClRange; SatElite(const SatElite&); const SatElite& operator=(const SatElite&); // For each var v struct OccurList { OccurList() : pos(0), bce(0), dirty(0), neg(0), litMark(0) {} ClWList refs; // left : ids of clauses containing v or ~v (var() == id, sign() == v or ~v) // right: ids of clauses watching v or ~v (literal 0 is the watched literal) uint32 pos:30; // number of *relevant* clauses containing v uint32 bce:1; // in BCE queue? uint32 dirty:1; // does clauses contain removed clauses? uint32 neg:30; // number of *relevant* clauses containing v uint32 litMark:2; // 00: no literal of v marked, 01: v marked, 10: ~v marked uint32 numOcc() const { return pos + neg; } uint32 cost() const { return pos * neg; } ClRange clauseRange() const { return ClRange(const_cast(refs).left_begin(), const_cast(refs).left_end()); } void clear() { this->~OccurList(); new (this) OccurList(); } void addWatch(uint32 clId) { refs.push_right(clId); } void removeWatch(uint32 clId) { refs.erase_right(std::find(refs.right_begin(), refs.right_end(), clId)); } void add(uint32 id, bool sign){ pos += uint32(!sign); neg += uint32(sign); refs.push_left(Literal(id, sign)); } void remove(uint32 id, bool sign, bool updateClauseList) { pos -= uint32(!sign); neg -= uint32(sign); if (updateClauseList) { refs.erase_left(std::find(refs.left_begin(), refs.left_end(), Literal(id, sign))); } else { dirty = 1; } } // note: only one literal of v shall be marked at a time bool marked(bool sign) const { return (litMark & (1+int(sign))) != 0; } void mark(bool sign) { litMark = (1+int(sign)); } void unmark() { litMark = 0; } }; struct LessOccCost { explicit LessOccCost(OccurList*& occ) : occ_(occ) {} bool operator()(Var v1, Var v2) const { return occ_[v1].cost() < occ_[v2].cost(); } private: const LessOccCost& operator=(LessOccCost&); OccurList*& occ_; }; typedef bk_lib::indexed_priority_queue ElimHeap; Clause* peekSubQueue() const { assert(qFront_ < queue_.size()); return (Clause*)clause( queue_[qFront_] ); } inline Clause* popSubQueue(); inline void addToSubQueue(uint32 clauseId); void updateHeap(Var v) { assert(ctx_); if (!ctx_->varInfo(v).frozen() && !ctx_->eliminated(v)) { elimHeap_.update(v); if (occurs_[v].bce == 0 && occurs_[0].bce != 0) { occurs_[0].addWatch(v); occurs_[v].bce = 1; } } } inline uint32 findUnmarkedLit(const Clause& c, uint32 x) const; void attach(uint32 cId, bool initialClause); void detach(uint32 cId); void bceVeRemove(uint32 cId, bool freeId, Var v, bool blocked); bool propagateFacts(); bool backwardSubsume(); Literal subsumes(const Clause& c, const Clause& other, Literal res) const; bool strengthenClause(uint32 clauseId, Literal p); bool subsumed(LitVec& cl); bool eliminateVars(); bool bce(); bool bceVe(Var v, uint32 maxCnt); ClRange splitOcc(Var v, bool mark); bool trivialResolvent(const Clause& c2, Var v) const; void markAll(const Literal* lits, uint32 size) const; void unmarkAll(const Literal* lits, uint32 size) const; bool addResolvent(uint32 newId, const Clause& c1, const Clause& c2); bool cutoff(Var v) const { return opts_->occLimit(occurs_[v].pos, occurs_[v].neg) || (occurs_[v].cost() == 0 && ctx_->preserveModels()); } bool timeout() const { return time(0) > timeout_; } enum OccSign { pos = 0, neg = 1}; OccurList* occurs_; // occur list for each variable ElimHeap elimHeap_; // candidates for variable elimination; ordered by increasing occurrence-cost VarVec occT_[2]; // temporary clause lists used in eliminateVar ClauseList resCands_; // pairs of clauses to be resolved LitVec resolvent_; // temporary, used in addResolvent VarVec queue_; // indices of clauses waiting for subsumption-check uint32 qFront_; // front of queue_, i.e. [queue_.begin()+qFront_, queue.end()) is the subsumption queue uint32 facts_; // [facts_, solver.trail.size()): new top-level facts std::time_t timeout_; // stop once time > timeout_ }; } #endif clingo-5.2.2/clasp/clasp/shared_context.h000066400000000000000000001201621320011352300203520ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_SHARED_CONTEXT_H_INCLUDED #define CLASP_SHARED_CONTEXT_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include #include /*! * \file * \brief Contains common types shared between different solvers. */ namespace Clasp { class Assignment; class SharedLiterals; struct SolverStats; class StatisticObject; typedef Asp::PrgDepGraph PrgDepGraph; //! An immutable string with efficient copying. /*! * \ingroup misc */ class ConstString { public: //! Creates a string from str. /*! * \note If o is Ownership_t::Acquire (the default), str is copied. * Otherwise, no copy is made and the lifetime of str shall extend * past that of the constructed object. */ ConstString(const char* str = "", Ownership_t::Type o = Ownership_t::Acquire); //! Creates a copy of str. ConstString(const StrView& str); ConstString(const ConstString& other); ~ConstString(); static ConstString fromLiteral(const char* str) { return ConstString(str, Ownership_t::Retain); } ConstString& operator=(const ConstString& rhs); const char* c_str() const; operator const char* () const { return c_str(); } void swap(ConstString& o); private: typedef uint64 RefType; RefType ref_; }; /** * \defgroup shared SharedContext * \brief %SharedContext and related types. */ //! Base class for event handlers. /*! * \ingroup shared */ class EventHandler : public ModelHandler { public: //! Creates a handler for events with given verbosity or lower. explicit EventHandler(Event::Verbosity verbosity = Event::verbosity_quiet); virtual ~EventHandler(); //! Sets the verbosity for the given event source. /*! * Events with higher verbosity are not dispatched to this handler. */ void setVerbosity(Event::Subsystem sys, Event::Verbosity verb); //! Sets the active event source to sys if sys is not yet active. bool setActive(Event::Subsystem sys); Event::Subsystem active() const; uint32 verbosity(Event::Subsystem sys) const { return (uint32(verb_) >> (uint32(sys)<(ev.system))) { onEvent(ev); } } virtual void onEvent(const Event& /* ev */) {} virtual bool onModel(const Solver&, const Model&) { return true; } private: enum { VERB_SHIFT = 2u, VERB_MAX = 15u }; EventHandler(const EventHandler&); EventHandler& operator=(const EventHandler&); uint16 verb_; uint16 sys_; }; //! Event type for log or warning messages. /*! * \ingroup enumerator */ struct LogEvent : Event_t { enum Type { Message = 'M', Warning = 'W' }; LogEvent(Subsystem sys, Verbosity verb, Type t, const Solver* s, const char* what) : Event_t(sys, verb), solver(s), msg(what) { op = static_cast(t); } bool isWarning() const { return op == static_cast(Warning); } const Solver* solver; const char* msg; }; //! Base class for preprocessors working on clauses only. /*! * \ingroup shared */ class SatPreprocessor { public: //! A clause class optimized for preprocessing. class Clause { public: static Clause* newClause(const Literal* lits, uint32 size); static uint64 abstractLit(Literal p) { return uint64(1) << ((p.var()-1) & 63); } uint32 size() const { return size_; } const Literal& operator[](uint32 x) const { return lits_[x]; } bool inQ() const { return inQ_ != 0; } uint64 abstraction() const { return data_.abstr; } Clause* next() const { return data_.next; } bool marked() const { return marked_ != 0;} Literal& operator[](uint32 x) { return lits_[x]; } void setInQ(bool b) { inQ_ = (uint32)b;} void setMarked(bool b) { marked_ = (uint32)b;} uint64& abstraction() { return data_.abstr; } Clause* linkRemoved(Clause* next) { data_.next = next; return this; } void strengthen(Literal p); void simplify(Solver& s); void destroy(); private: Clause(const Literal* lits, uint32 size); union { uint64 abstr; // abstraction of literals Clause* next; // next removed clause } data_; uint32 size_ : 30; // size of the clause uint32 inQ_ : 1; // in todo-queue? uint32 marked_ : 1; // a marker flag Literal lits_[1]; // literals of the clause: [lits_[0], lits_[size_]) }; SatPreprocessor(); virtual ~SatPreprocessor(); //! Creates a clone of this preprocessor. /*! * \note The function does not clone any clauses already added to *this. */ virtual SatPreprocessor* clone() = 0; uint32 numClauses() const { return (uint32)clauses_.size(); } //! Adds a clause to the preprocessor. /*! * \pre clause is not a tautology (i.e. does not contain both l and ~l) * \pre clause is a set (i.e. does not contain l more than once) * \return true if clause was added. False if adding the clause makes the problem UNSAT */ bool addClause(const LitVec& cl) { return addClause(!cl.empty() ? &cl[0] : 0, sizeVec(cl)); } bool addClause(const Literal* clause, uint32 size); //! Runs the preprocessor on all clauses that were previously added. /*! * \pre A ctx.startAddConstraint() was called and has variables for all added clauses. */ bool preprocess(SharedContext& ctx, SatPreParams& opts); bool preprocess(SharedContext& ctx); //! Force removal of state & clauses. void cleanUp(bool discardEliminated = false); //! Extends the model in m with values for any eliminated variables. void extendModel(ValueVec& m, LitVec& open); struct Stats { Stats() : clRemoved(0), clAdded(0), litsRemoved(0) {} uint32 clRemoved; uint32 clAdded; uint32 litsRemoved; } stats; typedef SatPreParams Options; protected: typedef PodVector::type ClauseList; virtual bool initPreprocess(SatPreParams& opts) = 0; virtual bool doPreprocess() = 0; virtual void doExtendModel(ValueVec& m, LitVec& open) = 0; virtual void doCleanUp() = 0; Clause* clause(uint32 clId) { return clauses_[clId]; } const Clause* clause(uint32 clId) const { return clauses_[clId]; } void freezeSeen(); void discardClauses(bool discardEliminated); void setClause(uint32 clId, const LitVec& cl) { clauses_[clId] = Clause::newClause(&cl[0], (uint32)cl.size()); } void destroyClause(uint32 clId){ clauses_[clId]->destroy(); clauses_[clId] = 0; ++stats.clRemoved; } void eliminateClause(uint32 id){ elimTop_ = clauses_[id]->linkRemoved(elimTop_); clauses_[id] = 0; ++stats.clRemoved; } SharedContext* ctx_; // current context const Options* opts_; // active options Clause* elimTop_; // stack of blocked/eliminated clauses private: SatPreprocessor(const SatPreprocessor&); SatPreprocessor& operator=(const SatPreprocessor&); ClauseList clauses_; // initial non-unit clauses LitVec units_; // initial unit clauses Range32 seen_; // vars seen in previous step }; /////////////////////////////////////////////////////////////////////////////// // Problem statistics /////////////////////////////////////////////////////////////////////////////// /*! * \addtogroup shared * @{ */ //! A struct for aggregating basic problem statistics. struct ProblemStats { ProblemStats() { reset(); } struct { uint32 num, eliminated, frozen; } vars; struct { uint32 other, binary, ternary; } constraints; uint32 acycEdges; uint32 complexity; void reset() { std::memset(this, 0, sizeof(*this)); } uint32 numConstraints() const { return constraints.other + constraints.binary + constraints.ternary; } void diff(const ProblemStats& o) { vars.num = std::max(vars.num, o.vars.num)-std::min(vars.num, o.vars.num); vars.eliminated = std::max(vars.eliminated, o.vars.eliminated)-std::min(vars.eliminated, o.vars.eliminated); vars.frozen = std::max(vars.frozen, o.vars.frozen)-std::min(vars.frozen, o.vars.frozen); constraints.other = std::max(constraints.other, o.constraints.other) - std::min(constraints.other, o.constraints.other); constraints.binary = std::max(constraints.binary, o.constraints.binary) - std::min(constraints.binary, o.constraints.binary); constraints.ternary= std::max(constraints.ternary, o.constraints.ternary) - std::min(constraints.ternary, o.constraints.ternary); acycEdges = std::max(acycEdges, o.acycEdges) - std::min(acycEdges, o.acycEdges); } void accu(const ProblemStats& o) { vars.num += o.vars.num; vars.eliminated += o.vars.eliminated; vars.frozen += o.vars.frozen; constraints.other += o.constraints.other; constraints.binary += o.constraints.binary; constraints.ternary += o.constraints.ternary; acycEdges += o.acycEdges; } // StatisticObject static uint32 size(); static const char* key(uint32 i); StatisticObject at(const char* k) const; }; //! Stores static information about a variable. struct VarInfo { //! Possible flags. enum Flag { Mark_p = 0x1u, //!< Mark for positive literal. Mark_n = 0x2u, //!< Mark for negative literal. Input = 0x4u, //!< Is this var an input variable? Body = 0x8u, //!< Is this var representing a body? Eq = 0x10u, //!< Is this var representing both a body and an atom? Nant = 0x20u, //!< Is this var in NAnt(P)? Frozen = 0x40u, //!< Is the variable frozen? Output = 0x80u //!< Is the variable an output variable? }; static uint8 flags(VarType t) { if (t == Var_t::Body) { return VarInfo::Body; } if (t == Var_t::Hybrid){ return VarInfo::Eq; } return 0; } explicit VarInfo(uint8 r = 0) : rep(r) { } //! Returns the type of the variable (or Var_t::Hybrid if variable was created with parameter eq=true). VarType type() const { return has(VarInfo::Eq) ? Var_t::Hybrid : VarType(Var_t::Atom + has(VarInfo::Body)); } //! Returns whether var is part of negative antecedents (occurs negatively or in the head of a choice rule). bool nant() const { return has(VarInfo::Nant); } //! Returns true if var is excluded from variable elimination. bool frozen() const { return has(VarInfo::Frozen); } //! Returns true if var is an input variable. bool input() const { return has(VarInfo::Input); } //! Returns true if var is marked as output variable. bool output() const { return has(VarInfo::Output); } //! Returns the preferred sign of this variable w.r.t its type. /*! * \return false (i.e no sign) if var originated from body, otherwise true. */ bool preferredSign() const { return !has(VarInfo::Body); } bool has(Flag f) const { return (rep & flag(f)) != 0; } bool has(uint32 f) const { return (rep & f) != 0; } bool hasAll(uint32 f)const { return (rep & f) == f; } void set(Flag f) { rep |= flag(f); } void toggle(Flag f) { rep ^= flag(f); } static uint8 flag(Flag x) { return uint8(x); } uint8 rep; }; //! A class for efficiently storing and propagating binary and ternary clauses. /*! * \ingroup shared_con */ class ShortImplicationsGraph { public: ShortImplicationsGraph(); ~ShortImplicationsGraph(); enum ImpType { binary_imp = 2, ternary_imp = 3 }; //! Makes room for nodes number of nodes. void resize(uint32 nodes); //! Mark the instance as shared/unshared. /*! * A shared instance adds learnt binary/ternary clauses * to specialized shared blocks of memory. */ void markShared(bool b) { shared_ = b; } //! Adds the given constraint to the implication graph. /*! * \return true iff a new implication was added. */ bool add(ImpType t, bool learnt, const Literal* lits); //! Removes p and its implications. /*! * \pre s.isTrue(p) */ void removeTrue(const Solver& s, Literal p); //! Propagates consequences of p following from binary and ternary clauses. /*! * \pre s.isTrue(p) */ bool propagate(Solver& s, Literal p) const; //! Propagates immediate consequences of p following from binary clauses only. bool propagateBin(Assignment& out, Literal p, uint32 dl) const; //! Checks whether there is a reverse arc implying p and if so returns it in out. bool reverseArc(const Solver& s, Literal p, uint32 maxLev, Antecedent& out) const; uint32 numBinary() const { return bin_[0]; } uint32 numTernary()const { return tern_[0]; } uint32 numLearnt() const { return bin_[1] + tern_[1]; } uint32 numEdges(Literal p) const; uint32 size() const { return sizeVec(graph_); } //! Applies op on all unary- and binary implications following from p. /*! * OP must provide two functions: * - bool unary(Literal, Literal) * - bool binary(Literal, Literal, Literal) * The first argument will be p, the second (resp. third) the unary * (resp. binary) clause implied by p. * \note For learnt imps, at least one literal has its watch-flag set. */ template bool forEach(Literal p, const OP& op) const { const ImplicationList& x = graph_[p.id()]; if (x.empty()) return true; ImplicationList::const_right_iterator rEnd = x.right_end(); // prefetch for (ImplicationList::const_left_iterator it = x.left_begin(), end = x.left_end(); it != end; ++it) { if (!op.unary(p, *it)) { return false; } } for (ImplicationList::const_right_iterator it = x.right_begin(); it != rEnd; ++it) { if (!op.binary(p, it->first, it->second)) { return false; } } #if CLASP_HAS_THREADS for (Block* b = (x).learnt; b ; b = b->next) { p.flag(); bool r = true; for (Block::const_iterator imp = b->begin(), endOf = b->end(); imp != endOf; ) { if (!imp->flagged()) { r = op.binary(p, imp[0], imp[1]); imp += 2; } else { r = op.unary(p, imp[0]); imp += 1; } if (!r) { return false; } } } #endif return true; } private: ShortImplicationsGraph(const ShortImplicationsGraph&); ShortImplicationsGraph& operator=(ShortImplicationsGraph&); struct Propagate; struct ReverseArc; #if CLASP_HAS_THREADS struct Block { typedef Clasp::mt::atomic atomic_size; typedef Clasp::mt::atomic atomic_ptr; typedef const Literal* const_iterator; typedef Literal* iterator; enum { block_cap = (64 - (sizeof(atomic_size)+sizeof(atomic_ptr)))/sizeof(Literal) }; explicit Block(); const_iterator begin() const { return data; } const_iterator end() const { return data+size(); } iterator end() { return data+size(); } uint32 size() const { return size_lock >> 1; } bool tryLock(uint32& lockedSize); void addUnlock(uint32 lockedSize, const Literal* x, uint32 xs); atomic_ptr next; atomic_size size_lock; Literal data[block_cap]; }; typedef Block::atomic_ptr SharedBlockPtr; typedef bk_lib::left_right_sequence, 64-sizeof(SharedBlockPtr)> ImpListBase; struct ImplicationList : public ImpListBase { ImplicationList() : ImpListBase() { learnt = 0; } ImplicationList(const ImplicationList& other) : ImpListBase(other), learnt() { learnt = static_cast(other.learnt); } ImplicationList& operator=(const ImplicationList& other) { ImpListBase::operator=(other); learnt = static_cast(other.learnt); return *this; } ~ImplicationList(); bool hasLearnt(Literal q, Literal r = lit_false()) const; void addLearnt(Literal q, Literal r = lit_false()); void simplifyLearnt(const Solver& s); bool empty() const { return ImpListBase::empty() && learnt == static_cast(0); } void move(ImplicationList& other); void clear(bool b); SharedBlockPtr learnt; }; #else typedef bk_lib::left_right_sequence, 64> ImplicationList; #endif ImplicationList& getList(Literal p) { return graph_[p.id()]; } void remove_bin(ImplicationList& w, Literal p); void remove_tern(ImplicationList& w, Literal p); typedef PodVector::type ImpLists; ImpLists graph_; // one implication list for each literal uint32 bin_[2]; // number of binary constraints (0: problem / 1: learnt) uint32 tern_[2]; // number of ternary constraints(0: problem / 1: learnt) bool shared_; }; //! Base class for distributing learnt knowledge between solvers. class Distributor { public: struct Policy { enum Types { no = 0, conflict = Constraint_t::Conflict, loop = Constraint_t::Loop, all = conflict | loop, implicit = all + 1 }; Policy(uint32 a_sz = 0, uint32 a_lbd = 0, uint32 a_type = 0) : size(a_sz), lbd(a_lbd), types(a_type) {} uint32 size : 22; /*!< Allow distribution up to this size only. */ uint32 lbd : 7; /*!< Allow distribution up to this lbd only. */ uint32 types : 3; /*!< Restrict distribution to these types. */ }; static uint64 mask(uint32 i) { return uint64(1) << i; } static uint32 initSet(uint32 sz) { return (uint64(1) << sz) - 1; } static bool inSet(uint64 s, uint32 id) { return (s & mask(id)) != 0; } explicit Distributor(const Policy& p); virtual ~Distributor(); bool isCandidate(uint32 size, uint32 lbd, uint32 type) const { return size <= policy_.size && lbd <= policy_.lbd && ((type & policy_.types) != 0); } virtual void publish(const Solver& source, SharedLiterals* lits) = 0; virtual uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut) = 0; private: Distributor(const Distributor&); Distributor& operator=(const Distributor&); Policy policy_; }; //! Output table that contains predicates to be output on model. class OutputTable { public: typedef ConstString NameType; typedef Range32 RangeType; struct PredType { NameType name; Literal cond; uint32 user; }; typedef PodVector::type FactVec; typedef PodVector::type PredVec; typedef FactVec::const_iterator fact_iterator; typedef PredVec::const_iterator pred_iterator; typedef num_iterator range_iterator; typedef LitVec::const_iterator lit_iterator; OutputTable(); ~OutputTable(); //! Ignore predicates starting with c. void setFilter(char c); //! Adds a fact. bool add(const NameType& fact); //! Adds an output predicate, i.e. n is output if c is true. bool add(const NameType& n, Literal c, uint32 u = 0); //! Sets a range of output variables. void setVarRange(const RangeType& r); void setProjectMode(ProjectMode m); //! Returns whether n would be filtered out. bool filter(const NameType& n) const; fact_iterator fact_begin() const { return facts_.begin(); } fact_iterator fact_end() const { return facts_.end(); } pred_iterator pred_begin() const { return preds_.begin(); } pred_iterator pred_end() const { return preds_.end(); } range_iterator vars_begin() const { return range_iterator(vars_.lo); } range_iterator vars_end() const { return range_iterator(vars_.hi); } RangeType vars_range() const { return vars_; } ProjectMode projectMode()const { return projMode_ ? static_cast(projMode_) : hasProject() ? ProjectMode_t::Explicit : ProjectMode_t::Output; } bool hasProject() const { return !proj_.empty(); } lit_iterator proj_begin() const { return proj_.begin(); } lit_iterator proj_end() const { return proj_.end(); } void addProject(Literal x); //! Returns the number of output elements, counting each element in a var range. uint32 size() const; uint32 numFacts() const { return static_cast(facts_.size()); } uint32 numPreds() const { return static_cast(preds_.size()); } uint32 numVars() const { return static_cast(vars_.hi - vars_.lo); } //! An optional callback for getting additional theory output. class Theory { public: virtual ~Theory(); //! Called once on new model m. Shall return 0 to indicate no output. virtual const char* first(const Model& m) = 0; //! Shall return 0 to indicate no output. virtual const char* next() = 0; }* theory; private: FactVec facts_; PredVec preds_; LitVec proj_; Range32 vars_; int projMode_; char hide_; }; //! A type for storing information to be used in clasp's domain heuristic. class DomainTable { public: DomainTable(); //! A type storing a single domain modification for a variable. class ValueType { public: ValueType(Var v, DomModType t, int16 bias, uint16 prio, Literal cond); bool hasCondition() const { return cond_ != 0; } Literal cond() const { return Literal::fromId(cond_); } Var var() const { return var_; } DomModType type() const; int16 bias() const { return bias_; } uint16 prio() const { return prio_; } bool comp() const { return comp_ != 0; } private: uint32 cond_ : 31; uint32 comp_ : 1; uint32 var_ : 30; uint32 type_ : 2; int16 bias_; uint16 prio_; }; typedef PodVector::type DomVec; typedef DomVec::const_iterator iterator; void add(Var v, DomModType t, int16 bias, uint16 prio, Literal cond); uint32 simplify(); void reset(); bool empty() const; uint32 size() const; iterator begin() const; iterator end() const; LitVec* assume; class DefaultAction { public: virtual ~DefaultAction(); virtual void atom(Literal p, HeuParams::DomPref, uint32 strat) = 0; }; static void applyDefault(const SharedContext& ctx, DefaultAction& action, uint32 prefSet = 0); private: static bool cmp(const ValueType& lhs, const ValueType& rhs) { return lhs.cond() < rhs.cond() || (lhs.cond() == rhs.cond() && lhs.var() < rhs.var()); } DomVec entries_; uint32 seen_; // size of domain table after last simplify }; //! Aggregates information to be shared between solver objects. /*! * Among other things, SharedContext objects store * static information on variables, an output table, as well as the * binary and ternary implication graph of the input problem. * * Furthermore, a SharedContext object always stores a distinguished * master solver that is used to store and simplify problem constraints. * Additional solvers can be added via SharedContext::pushSolver(). * Once initialization is completed, any additional solvers must be attached * to this object by calling SharedContext::attach(). */ class SharedContext { public: typedef PodVector::type SolverVec; typedef SingleOwnerPtr SccGraph; typedef SingleOwnerPtr ExtGraph; typedef Configuration* ConfigPtr; typedef SingleOwnerPtr DistrPtr; typedef const ProblemStats& StatsCRef; typedef DomainTable DomTab; typedef OutputTable Output; typedef LitVec::size_type size_type; typedef ShortImplicationsGraph ImpGraph; typedef const ImpGraph& ImpGraphRef; typedef EventHandler* LogPtr; typedef SingleOwnerPtrSatPrePtr; typedef SharedMinimizeData* MinPtr; enum ResizeMode { resize_reserve = 0u, resize_push = 1u, resize_pop = 2u, resize_resize = 3u}; enum PreproMode { prepro_preserve_models = 1u, prepro_preserve_shown = 2u }; enum ReportMode { report_default = 0u, report_conflict = 1u }; enum SolveMode { solve_once = 0u, solve_multi = 1u }; /*! * \name Configuration * \brief Functions for creating and configuring a shared context. * @{ */ //! Creates a new object for sharing variables and the binary and ternary implication graph. explicit SharedContext(); ~SharedContext(); //! Resets this object to the state after default construction. void reset(); //! Enables event reporting via the given event handler. void setEventHandler(LogPtr r, ReportMode m = report_default) { progress_ = r; share_.report = uint32(m); } //! Sets solve mode, which can be used by other objects to query whether multi-shot solving is active. void setSolveMode(SolveMode m); //! Sets how to handle physical sharing of constraints. void setShareMode(ContextParams::ShareMode m); //! Sets whether the short implication graph should be used for storing short learnt constraints. void setShortMode(ContextParams::ShortMode m); //! Sets maximal number of solvers sharing this object. void setConcurrency(uint32 numSolver, ResizeMode m = resize_reserve); //! If b is true, sets preprocessing mode to model-preserving operations only. void setPreserveModels(bool b = true) { setPreproMode(prepro_preserve_models, b); } //! If b is true, excludes all shown variables from variable elimination. void setPreserveShown(bool b = true) { setPreproMode(prepro_preserve_shown, b); } //! Adds an additional solver to this object and returns it. Solver& pushSolver(); //! Configures the statistic object of attached solvers. /*! * The level determines the amount of extra statistics. * \see ExtendedStats * \see JumpStats */ void enableStats(uint32 level); //! Sets the configuration for this object and its attached solvers. /*! * \note If ownership is Ownership_t::Acquire, ownership of c is transferred. */ void setConfiguration(Configuration* c, Ownership_t::Type ownership); SatPrePtr satPrepro; /*!< Preprocessor for simplifying the problem. */ SccGraph sccGraph; /*!< Program dependency graph - only used for ASP-problems. */ ExtGraph extGraph; /*!< External dependency graph - given by user. */ //! Returns the current configuration used in this object. ConfigPtr configuration() const { return config_.get(); } //! Returns the active event handler or 0 if none was set. LogPtr eventHandler() const { return progress_; } //! Returns whether this object seeds the RNG of new solvers. bool seedSolvers() const { return share_.seed != 0; } //! Returns the number of solvers that can share this object. uint32 concurrency() const { return share_.count; } bool preserveModels() const { return (share_.satPreM & prepro_preserve_models) != 0; } bool preserveShown() const { return (share_.satPreM & prepro_preserve_shown) != 0; } //! Returns whether physical sharing is enabled for constraints of type t. bool physicalShare(ConstraintType t) const { return (share_.shareM & (1 + (t != Constraint_t::Static))) != 0; } //! Returns whether pyhiscal sharing of problem constraints is enabled. bool physicalShareProblem() const { return (share_.shareM & ContextParams::share_problem) != 0; } //! Returns whether short constraints of type t can be stored in the short implication graph. bool allowImplicit(ConstraintType t) const { return t != Constraint_t::Static ? share_.shortM != ContextParams::short_explicit : !isShared(); } //! Returns the configured solve mode. SolveMode solveMode() const { return static_cast(share_.solveM); } //@} /*! * \name Problem introspection * \brief Functions for querying information about the problem. */ //@{ //! Returns true unless the master has an unresolvable top-level conflict. bool ok() const; //! Returns whether the problem is currently frozen and therefore ready for being solved. bool frozen() const { return share_.frozen;} //! Returns whether more than one solver is actively working on the problem. bool isShared() const { return frozen() && concurrency() > 1; } //! Returns whether the problem is more than a simple CNF. bool isExtended() const { return stats_.vars.frozen != 0; } //! Returns whether this object has a solver associcated with the given id. bool hasSolver(uint32 id) const { return id < solvers_.size(); } //! Returns the master solver associated with this object. Solver* master() const { return solver(0); } //! Returns the solver with the given id. Solver* solver(uint32 id) const { return solvers_[id]; } //! Returns the number of problem variables. /*! * \note The special sentinel-var 0 is not counted, i.e. numVars() returns * the number of problem-variables. * To iterate over all problem variables use a loop like: * \code * for (Var i = 1; i <= numVars(); ++i) {...} * \endcode */ uint32 numVars() const { return static_cast(varInfo_.size() - 1); } //! Returns the number of eliminated vars. uint32 numEliminatedVars() const { return stats_.vars.eliminated; } //! Returns true if var represents a valid variable in this problem. /*! * \note The range of valid variables is [1..numVars()]. The variable 0 * is a special sentinel variable. */ bool validVar(Var var) const { return var < static_cast(varInfo_.size()); } //! Returns information about the given variable. VarInfo varInfo(Var v) const { assert(validVar(v)); return varInfo_[v]; } //! Returns true if v is currently eliminated, i.e. no longer part of the problem. bool eliminated(Var v) const; bool marked(Literal p) const { return varInfo(p.var()).has(VarInfo::Mark_p + p.sign()); } //! Returns the number of problem constraints. uint32 numConstraints() const; //! Returns the number of binary constraints. uint32 numBinary() const { return btig_.numBinary(); } //! Returns the number of ternary constraints. uint32 numTernary() const { return btig_.numTernary(); } //! Returns the number of unary constraints. uint32 numUnary() const { return lastTopLevel_; } //! Returns an estimate of the problem complexity based on the number and type of constraints. uint32 problemComplexity() const; //! Returns whether the problem contains minimize (i.e. weak) constraints. bool hasMinimize() const; StatsCRef stats() const { return stats_; } //@} /*! * \name Problem setup * \brief Functions for specifying the problem. * * Problem specification is a four-stage process: * -# Add variables to the SharedContext object. * -# Call startAddConstraints(). * -# Add problem constraints. * -# Call endInit() to finish the initialization process. * . * \note After endInit() was called, other solvers can be attached to this object. * \note In incremental setting, the process must be repeated for each incremental step. * * \note Problem specification is *not* thread-safe, i.e. during initialization no other thread shall * access the context. * * \note !frozen() is a precondition for all functions in this group! * @{ */ //! Unfreezes a frozen program and prepares it for updates. /*! * The function also triggers forgetting of volatile knowledge and removes * any auxiliary variables. * \see requestStepVar() * \see Solver::popAuxVar() */ bool unfreeze(); //! Adds a new variable and returns its numerical id. /*! * \param type Type of variable. * \param flags Additional information associated with the new variable. * \note Problem variables are numbered from 1 onwards! */ Var addVar(VarType type, uint8 flags = VarInfo::Nant | VarInfo::Input) { return addVars(1, type, flags); } Var addVars(uint32 nVars, VarType type, uint8 flags = VarInfo::Nant | VarInfo::Input); //! Removes the n most recently added problem variables. /*! * \pre The variables have either not yet been committed by a call to startAddConstraints() * or they do not occur in any constraint. */ void popVars(uint32 n = 1); //! Freezes/defreezes a variable (a frozen var is exempt from Sat-preprocessing). void setFrozen(Var v, bool b); //! Marks/unmarks v as input variable. void setInput(Var v, bool b) { set(v, VarInfo::Input, b); } //! Marks/unmarks v as output variable. void setOutput(Var v, bool b) { set(v, VarInfo::Output, b); } //! Marks/unmarks v as part of negative antecedents. void setNant(Var v, bool b) { set(v, VarInfo::Nant, b); } void setVarEq(Var v, bool b) { set(v, VarInfo::Eq, b); } void set(Var v, VarInfo::Flag f, bool b) { if (b != varInfo(v).has(f)) varInfo_[v].toggle(f); } void mark(Literal p) { assert(validVar(p.var())); varInfo_[p.var()].rep |= (VarInfo::Mark_p + p.sign()); } void unmark(Var v) { assert(validVar(v)); varInfo_[v].rep &= ~(VarInfo::Mark_p|VarInfo::Mark_n); } //! Eliminates the variable v from the problem. /*! * \pre v must not occur in any constraint and frozen(v) == false and value(v) == value_free */ void eliminate(Var v); //! Prepares the master solver so that constraints can be added. /*! * Must be called to publish previously added variables to master solver * and before constraints over these variables can be added. * \return The master solver associated with this object. */ Solver& startAddConstraints(uint32 constraintGuess = 100); //! A convenience method for adding facts to the master. bool addUnary(Literal x); //! A convenience method for adding binary clauses. bool addBinary(Literal x, Literal y); //! A convenience method for adding ternary clauses. bool addTernary(Literal x, Literal y, Literal z); //! A convenience method for adding constraints to the master. void add(Constraint* c); //! Add weak constraint :~ x.first \[x.second\@p\]. void addMinimize(WeightLiteral x, weight_t p); //! Returns a pointer to an optimized representation of all minimize constraints in this problem. MinPtr minimize(); //! List of output predicates and/or variables. Output output; //! Set of heuristic modifications. DomTab heuristic; //! Requests a special variable for tagging volatile knowledge in multi-shot solving. /*! * The step variable is created on the next call to endInit() and removed on the next * call to unfreeze(). * Once the step variable S is set, learnt constraints containing ~S are * considered to be "volatile" and removed on the next call to unfreeze(). * For this to work correctly, S shall be a root assumption during search. */ void requestStepVar(); //! Finishes initialization of the master solver. /*! * The function must be called once before search is started. After endInit() * was called, previously added solvers can be attached to the * shared context and learnt constraints may be added to solver. * \param attachAll If true, also calls attach() for all solvers that were added to this object. * \return If the constraints are initially conflicting, false. Otherwise, true. * \note * The master solver can't recover from top-level conflicts, i.e. if endInit() * returned false, the solver is in an unusable state. * \post frozen() */ bool endInit(bool attachAll = false); //@} /*! * \name (Parallel) solving * Functions to be called during (parallel) solving. * * \note If not otherwise noted, the functions in this group can be safely called * from multiple threads. * @{ */ //! Returns the active step literal (see requestStepVar()). Literal stepLiteral() const { return step_; } //! Attaches the solver with the given id to this object. /*! * \note It is safe to attach multiple solvers concurrently * but the master solver shall not change during the whole operation. * * \pre hasSolver(id) */ bool attach(uint32 id) { return attach(*solver(id)); } bool attach(Solver& s); //! Detaches the solver with the given id from this object. /*! * The function removes any tentative constraints from s. * Shall be called once after search has stopped. * \note The function is concurrency-safe w.r.t to different solver objects, * i.e. in a parallel search different solvers may call detach() * concurrently. */ void detach(uint32 id, bool reset = false) { return detach(*solver(id), reset); } void detach(Solver& s, bool reset = false); DistrPtr distributor;/*!< Distributor object to use for distribution of learnt constraints.*/ uint32 winner() const { return share_.winner; } void setWinner(uint32 sId) { share_.winner = std::min(sId, concurrency()); } //! Simplifies the problem constraints w.r.t the master's assignment. void simplify(bool shuffle); //! Removes the constraint with the given idx from the master's db. void removeConstraint(uint32 idx, bool detach); //! Removes all minimize constraints from this object. void removeMinimize(); //! Adds the given short implication to the short implication graph if possible. /*! * \return * - > 0 if implication was added. * - < 0 if implication can't be added because allowImplicit() is false for ct. * - = 0 if implication is subsumed by some constraint in the short implication graph. */ int addImp(ImpGraph::ImpType t, const Literal* lits, ConstraintType ct); //! Returns the number of learnt short implications. uint32 numLearntShort() const { return btig_.numLearnt(); } ImpGraphRef shortImplications() const { return btig_; } void simplifyShort(const Solver& s, Literal p); void report(const Event& ev) const { if (progress_) progress_->dispatch(ev); } bool report(const Solver& s, const Model& m) const { return !progress_ || progress_->onModel(s, m); } void report(const char* what, const Solver* s = 0) const; void report(Event::Subsystem sys) const; void warn(const char* what) const; ReportMode reportMode() const { return static_cast(share_.report); } void initStats(Solver& s) const; SolverStats& solverStats(uint32 sId) const; // stats of solver i const SolverStats& accuStats(SolverStats& out) const; // accumulates all solver stats in out MinPtr minimizeNoCreate() const; //@} private: SharedContext(const SharedContext&); SharedContext& operator=(const SharedContext&); bool unfreezeStep(); Literal addStepLit(); typedef SingleOwnerPtr Config; typedef PodVector::type VarVec; void setPreproMode(uint32 m, bool b); struct Minimize; ProblemStats stats_; // problem statistics VarVec varInfo_; // varInfo[v] stores info about variable v ImpGraph btig_; // binary-/ternary implication graph Config config_; // active configuration SolverVec solvers_; // solvers associated with this context Minimize* mini_; // pointer to set of weak constraints LogPtr progress_; // event handler or 0 if not used Literal step_; // literal for tagging enumeration/step constraints uint32 lastTopLevel_; // size of master's top-level after last init struct Share { // Additional data uint32 count :10; // max number of objects sharing this object uint32 winner :10; // id of solver that terminated the search uint32 shareM : 3; // physical sharing mode uint32 shortM : 1; // short clause mode uint32 solveM : 1; // solve mode uint32 frozen : 1; // is adding of problem constraints allowed? uint32 seed : 1; // set seed of new solvers uint32 satPreM : 2; // preprocessing mode uint32 report : 2; // report mode uint32 reserved: 1; Share() : count(1), winner(0), shareM((uint32)ContextParams::share_auto), shortM(0), solveM(0), frozen(0), seed(0), satPreM(0), report(0) {} } share_; }; //@} } #endif clingo-5.2.2/clasp/clasp/solve_algorithms.h000066400000000000000000000241221320011352300207200ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_SOLVE_ALGORITHMS_H_INCLUDED #define CLASP_SOLVE_ALGORITHMS_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include /*! * \file * \brief Defines top-level functions for solving problems. */ namespace Clasp { ///! \addtogroup enumerator //@{ //! Type for holding global solve limits. struct SolveLimits { explicit SolveLimits(uint64 conf = UINT64_MAX, uint64 r = UINT64_MAX) : conflicts(conf) , restarts(r) { } bool reached() const { return conflicts == 0 || restarts == 0; } bool enabled() const { return conflicts != UINT64_MAX || restarts != UINT32_MAX; } uint64 conflicts; /*!< Number of conflicts. */ uint64 restarts; /*!< Number of restarts. */ }; /////////////////////////////////////////////////////////////////////////////// // Basic solving /////////////////////////////////////////////////////////////////////////////// //! Basic (sequential) solving using given solving options. class BasicSolve { public: //! Creates a new object for solving with the given solver using the given solving options. /*! * If an optional solve limit is given, solving stops once this limit is reached. * \pre s is attached to a problem (SharedContext). */ BasicSolve(Solver& s, const SolveParams& p, const SolveLimits& lim = SolveLimits()); BasicSolve(Solver& s, const SolveLimits& lim = SolveLimits()); ~BasicSolve(); bool hasLimit() const { return limits_.enabled(); } //! Enables solving under the given assumptions. /*! * The use of assumptions allows for incremental solving. Literals contained * in assumptions are assumed to be true during search but can be undone afterwards. * * \param assumptions A list of unit assumptions to be assumed true. * \return false if assumptions are conflicting. */ bool assume(const LitVec& assumptions); //! Solves the path stored in the given solver using the given solving options. /*! * \return * - value_true if search stopped on a model. * - value_false if the search-space was completely examined. * - value_free if the given solve limit was hit. * * \note * The function maintains the current solving state (number of restarts, learnt limits, ...) * between calls. */ ValueRep solve(); //! Returns whether the given problem is satisfiable under the given assumptions. /*! * Calls assume(assumptions) followed by solve() but does not maintain any solving state. * \param assumptions Possibly empty set of assumptions to apply before solving. * \param init Call InitParams::randomize() before starting search? */ bool satisfiable(const LitVec& assumptions, bool init); //! Resets the internal solving state while keeping the solver and the solving options. void reset(bool reinit = false); //! Replaces *this with BasicSolve(s, p). void reset(Solver& s, const SolveParams& p, const SolveLimits& lim = SolveLimits()); Solver& solver() { return *solver_; } private: BasicSolve(const BasicSolve&); BasicSolve& operator=(const BasicSolve&); typedef const SolveParams Params; typedef SolveLimits Limits; struct State; Solver* solver_; // active solver Params* params_; // active solving options Limits limits_; // active solving limits State* state_; // internal solving state }; //! Event type for reporting basic solve events like restarts or deletion. struct BasicSolveEvent : SolveEvent { //! Type of operation that emitted the event. enum EventOp { event_none = 0, event_deletion = 'D', event_exit = 'E', event_grow = 'G', event_restart = 'R' }; BasicSolveEvent(const Solver& s, EventOp a_op, uint64 cLim, uint32 lLim) : SolveEvent(s, verbosity_max), cLimit(cLim), lLimit(lLim) { op = a_op; } uint64 cLimit; //!< Next conflict limit uint32 lLimit; //!< Next learnt limit }; /////////////////////////////////////////////////////////////////////////////// // General solve /////////////////////////////////////////////////////////////////////////////// class Enumerator; //! Interface for complex solve algorithms. /*! * \ingroup enumerator * \relates Solver * SolveAlgorithms implement complex algorithms like enumeration or optimization. */ class SolveAlgorithm { public: /*! * \param limit An optional solve limit applied in solve(). */ explicit SolveAlgorithm(const SolveLimits& limit = SolveLimits()); virtual ~SolveAlgorithm(); const Enumerator* enumerator() const { return enum_.get(); } const SolveLimits& limits() const { return limits_; } virtual bool interrupted()const = 0; const Model& model() const; void setEnumerator(Enumerator& e); void setEnumLimit(uint64 m) { enumLimit_= m; } void setLimits(const SolveLimits& x) { limits_ = x; } //! Runs the solve algorithm. /*! * \param ctx A context object containing the problem. * \param assume A list of initial unit-assumptions. * \param onModel Optional handler to be called on each model. * * \return * - true: if the search stopped before the search-space was exceeded. * - false: if the search-space was completely examined. * * \note * The use of assumptions allows for incremental solving. Literals contained * in assumptions are assumed to be true during search but are undone before solve returns. * * \note * Conceptually, solve() behaves as follows: * \code * start(ctx, assume); * while (next()) { * if (!report(model()) || enum_limit_reached()) { stop(); } * } * return more(); * \endcode * where report() notifies all registered model handlers. */ bool solve(SharedContext& ctx, const LitVec& assume = LitVec(), ModelHandler* onModel = 0); //! Prepares the solve algorithm for enumerating models. /*! * \pre The algorithm is not yet active. */ void start(SharedContext& ctx, const LitVec& assume = LitVec(), ModelHandler* onModel = 0); //! Searches for the next model and returns whether such a model was found. /*! * \pre start() was called. */ bool next(); //! Stops the algorithms. void stop(); //! Returns whether the last search completely exhausted the search-space. bool more(); //! Resets solving state and sticky messages like terminate. /*! * \note The function must be called between successive calls to solve(). */ virtual void resetSolve() = 0; //! Prepares the algorithm for handling (asynchronous) calls to SolveAlgorithm::interrupt(). virtual void enableInterrupts() = 0; //! Tries to terminate the current solve process. /*! * \note If enableInterrupts() was not called, SolveAlgorithm::interrupt() may return false * to signal that (asynchronous) termination is not supported. */ bool interrupt(); protected: SolveAlgorithm(const SolveAlgorithm&); SolveAlgorithm& operator=(const SolveAlgorithm&); //! The actual solve algorithm. virtual bool doSolve(SharedContext& ctx, const LitVec& assume) = 0; //! Shall return true if termination is supported, otherwise false. virtual bool doInterrupt() = 0; virtual void doStart(SharedContext& ctx, const LitVec& assume); virtual int doNext(int last); virtual void doStop(); bool reportModel(Solver& s) const; bool reportUnsat(Solver& s) const; Enumerator& enumerator() { return *enum_; } SharedContext& ctx() const { return *ctx_; } const LitVec& path() const { return *path_; } uint64 maxModels() const { return enumLimit_; } bool moreModels(const Solver& s) const; private: typedef SingleOwnerPtr EnumPtr; typedef SingleOwnerPtr PathPtr; enum { value_stop = value_false|value_true }; bool attach(SharedContext& ctx, ModelHandler* onModel); void detach(); SolveLimits limits_; SharedContext* ctx_; EnumPtr enum_; ModelHandler* onModel_; PathPtr path_; uint64 enumLimit_; double time_; int last_; }; //! A class that implements clasp's sequential solving algorithm. class SequentialSolve : public SolveAlgorithm { public: explicit SequentialSolve(const SolveLimits& limit = SolveLimits()); virtual bool interrupted() const; virtual void resetSolve(); virtual void enableInterrupts(); protected: virtual bool doSolve(SharedContext& ctx, const LitVec& assume); virtual bool doInterrupt(); virtual void doStart(SharedContext& ctx, const LitVec& assume); virtual int doNext(int last); virtual void doStop(); private: typedef SingleOwnerPtr SolvePtr; SolvePtr solve_; volatile int term_; }; //! Options for controlling solving. struct BasicSolveOptions { SolveLimits limit; //!< Solve limit (disabled by default). SolveAlgorithm* createSolveObject() const { return new SequentialSolve(limit); } static uint32 supportedSolvers() { return 1; } static uint32 recommendedSolvers() { return 1; } uint32 numSolver() const { return 1; } void setSolvers(uint32) {} bool defaultPortfolio() const { return false; } }; //@} } #endif clingo-5.2.2/clasp/clasp/solver.h000066400000000000000000001345611320011352300166620ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_SOLVER_H_INCLUDED #define CLASP_SOLVER_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include namespace Clasp { /** * \file * \defgroup solver Solver * \brief %Solver and related classes. */ //@{ //! clasp's Solver class. /*! * A Solver-object maintains the state and provides the functions * necessary to implement our CDNL-algorithm. * * The interface supports incremental solving (search under assumptions) as well as * solution enumeration. To make this possible the solver maintains two special * decision levels: the root-level and the backtrack-level. * * The root-level is the lowest decision level to which a search * can return. Conflicts on the root-level are non-resolvable and end a search - the * root-level therefore acts as an artificial top-level during search. * Incremental solving is then implemented by first adding a list of unit assumptions * and second initializing the root-level to the current decision level. * Once search terminates assumptions can be undone by calling clearAssumptions * and a new a search can be started using different assumptions. * * For model enumeration the solver maintains a backtrack-level that restricts * backjumping in order to prevent repeating already enumerated solutions. * The solver will never backjump above that level and conflicts on the backtrack-level * are resolved by backtracking, i.e. flipping the corresponding decision literal. * * \see "Conflict-Driven Answer Set Enumeration" for a detailed description of this approach. * */ class Solver { public: typedef PodVector::type ConstraintDB; typedef const ConstraintDB& DBRef; typedef SingleOwnerPtr HeuristicPtr; private: friend class SharedContext; // Creates an empty solver object with all strategies set to their default value. Solver(SharedContext* ctx, uint32 id); ~Solver(); // Resets a solver object to the state it had after construction. void reset(); void resetConfig(); void startInit(uint32 constraintGuess, const SolverParams& params); void updateVars(); bool cloneDB(const ConstraintDB& db); bool preparePost(); bool endInit(); bool endStep(uint32 top, const SolverParams& params); public: typedef SolverStrategies::SearchStrategy SearchMode; typedef SolverStrategies::UpdateMode UpdateMode; typedef SolverStrategies::WatchInit WatchInitMode; //! Returns a pointer to the shared context object of this solver. const SharedContext* sharedContext() const { return shared_; } //! Returns a pointer to the sat-preprocessor used by this solver. SatPreprocessor* satPrepro() const; //! Returns the solver's solve parameters. const SolveParams& searchConfig() const; SearchMode searchMode() const { return static_cast(strategy_.search); } UpdateMode updateMode() const { return static_cast(strategy_.upMode); } WatchInitMode watchInitMode() const { return static_cast(strategy_.initWatches); } uint32 compressLimit() const { return strategy_.compress ? strategy_.compress : UINT32_MAX; } bool restartOnModel()const { return strategy_.restartOnModel; } DecisionHeuristic* heuristic() const { return heuristic_.get();} uint32 id() const { return strategy_.id; } VarInfo varInfo(Var v) const { return shared_->validVar(v) ? shared_->varInfo(v) : VarInfo(); } const OutputTable& outputTable() const { return shared_->output; } Literal tagLiteral() const { return tag_; } bool isMaster() const { return this == sharedContext()->master(); } /*! * \name Setup functions * Functions in this group are typically used before a search is started. * @{ */ //! Adds the problem constraint c to the solver. /*! * Problem constraints shall only be added to the master solver of * a SharedContext object and only during the setup phase. * \pre this == sharedContext()->master() && !sharedContext()->frozen(). */ void add(Constraint* c); //! Adds a suitable representation of the given clause to the solver. /*! * Depending on the type and size of the given clause, the function * either adds a (learnt) constraint to this solver or an implication * to the shared implication graph. * \note If c is a problem clause, the precondition of add(Constraint* c) applies. */ bool add(const ClauseRep& c, bool isNew = true); //! Returns whether c can be stored in the shared short implication graph. bool allowImplicit(const ClauseRep& c) const { return c.isImp() ? shared_->allowImplicit(c.info.type()) && !c.info.aux() && (c.prep == 1 || (!auxVar(c.lits[0].var()) && !auxVar(c.lits[1].var()) && (c.size == 2 || !auxVar(c.lits[2].var())))) : c.size <= 1; } //! Returns the post propagator with the given priority or 0 if no such post propagator exists. PostPropagator* getPost(uint32 prio) const; //! Adds p as post propagator to this solver. /*! * \pre p was not added previously and is not part of any other solver. * \note Post propagators are stored and called in priority order. * \see PostPropagator::priority() */ bool addPost(PostPropagator* p); //! Removes p from the solver's list of post propagators. /*! * \note The function shall not be called during propagation of any other post propagator. */ void removePost(PostPropagator* p); //! Adds path to the current root-path and adjusts the root-level accordingly. bool pushRoot(const LitVec& path); bool pushRoot(Literal p); void setEnumerationConstraint(Constraint* c); //! Requests a special aux variable for tagging conditional knowledge. /*! * Once a tag variable t is set, learnt clauses containing ~t are * tagged as "conditional". Conditional clauses are removed once t becomes * unassigned or Solver::removeConditional() is called. Furthermore, calling * Solver::strengthenConditional() removes ~t from conditional clauses and * transforms them to unconditional knowledge. * * \note Typically, the tag variable is a root assumption and hence true during * the whole search. */ Var pushTagVar(bool pushToRoot); //@} /*! * \name CDNL functions * Top level functions that are important to the CDNL algorithm. * @{ */ //! Searches for a model as long as the given limit is not reached. /*! * The function searches for a model as long as none of the limits given by limit * is reached. The limits are updated during search. * * \param limit Imposed limit on conflicts and number of learnt constraints. * \param randf Pick next decision variable randomly with a probability of randf. * \return * - value_true: if a model was found. * - value_false: if the problem is unsatisfiable (under assumptions, if any). * - value_free: if search was stopped because limit was reached. * . * * \note search treats the root level as top-level, i.e. it will never backtrack below that level. */ ValueRep search(SearchLimits& limit, double randf = 0.0); ValueRep search(uint64 maxC, uint32 maxL, bool local = false, double rp = 0.0); //! Moves the root-level i levels down (i.e. away from the top-level). /*! * The root-level is similar to the top-level in that it cannot be * undone during search, i.e. the solver will not resolve conflicts that are on or * above the root-level. */ void pushRootLevel(uint32 i = 1) { levels_.root = std::min(decisionLevel(), levels_.root+i); levels_.flip = std::max(levels_.flip, levels_.root); } //! Moves the root-level i levels up (i.e. towards the top-level). /*! * The function removes all levels between the new root level and the current decision level, * resets the current backtrack-level, and re-assigns any implied literals. * \param i Number of root decisions to pop. * \param[out] popped Optional storage for popped root decisions. * \param aux Whether or not aux variables should be added to popped. * \post decisionLevel() == rootLevel() * \note The function first calls clearStopConflict() to remove any stop conflicts. * \note The function *does not* propagate any asserted literals. It is * the caller's responsibility to call propagate() after the function returned. */ bool popRootLevel(uint32 i = 1, LitVec* popped = 0, bool aux = true); //! Removes a previously set stop conflict and restores the root level. void clearStopConflict(); //! Returns the current root level. uint32 rootLevel() const { return levels_.root; } //! Removes any implications made between the top-level and the root-level. /*! * The function also resets the current backtrack-level and re-assigns learnt facts. * \note * Equivalent to popRootLevel(rootLevel()) followed by simplify(). */ bool clearAssumptions(); //! Adds c as a learnt constraint to the solver. void addLearnt(Constraint* c, uint32 size, ConstraintType type) { learnts_.push_back(c); stats.addLearnt(size, type); } void addLearnt(Constraint* c, uint32 size) { addLearnt(c, size, c->type()); } //! Tries to receive at most maxOut clauses. /*! * The function queries the distributor object for new clauses to be delivered to * this solver. Clauses are stored in out. * \return The number of clauses received. */ uint32 receive(SharedLiterals** out, uint32 maxOut) const; //! Distributes the clause in lits via the distributor. /*! * The function first calls the distribution strategy * to decides whether the clause is a valid candidate for distribution. * If so and a distributor was set, it distributes the clause and returns a handle to the * now shared literals of the clause. Otherwise, it returns 0. * * \param lits The literals of the clause. * \param size The number of literals in the clause. * \param extra Additional information about the clause. * \note * If the return value is not null, it is the caller's * responsibility to release the returned handle (i.e. by calling release()). * \note If the clause contains aux vars, it is not distributed. */ SharedLiterals* distribute(const Literal* lits, uint32 size, const ConstraintInfo& extra); //! Returns to the maximum of rootLevel() and backtrackLevel() and increases the number of restarts. void restart() { undoUntil(0); ++stats.restarts; ccInfo_.score().bumpActivity(); } enum UndoMode { undo_default = 0u, undo_pop_bt_level = 1u, undo_pop_proj_level = 2u, undo_save_phases = 4u }; //! Sets the backtracking level to dl. /*! * Depending on mode, the backtracking level either applies * to normal or projective solution enumeration. * \see "Solution Enumeration for Projected Boolean Search Problems". */ void setBacktrackLevel(uint32 dl, UndoMode mode = undo_pop_bt_level) { if (uint32(mode) >= levels_.mode) { levels_.flip = std::max(std::min(dl, decisionLevel()), rootLevel()); levels_.mode = std::max(uint32(mode & 3u), uint32(undo_pop_bt_level)); } } //! Returns the current backtracking level. uint32 backtrackLevel() const { return levels_.flip; } //! Returns the backjump level during an undo operation. uint32 jumpLevel() const { return decisionLevel() - levels_.jump; } //! Returns whether the solver can split-off work. bool splittable() const; //! Tries to split-off disjoint work from the solver's currrent guiding path and returns it in out. /*! * \return splittable() */ bool split(LitVec& out); //! Copies the solver's currrent guiding path to gp. /*! * \note The solver's guiding path consists of: * - the decisions from levels [1, rootLevel()] * - any literals that are implied on a level <= rootLevel() because of newly learnt * information. This particularly includes literals that were flipped during model enumeration. * * \param[out] out Where to store the guiding path. */ void copyGuidingPath(LitVec& out); //! If called on top-level, removes SAT-clauses + Constraints for which Constraint::simplify returned true. /*! * \note If this method is called on a decision-level > 0, it is a noop and will * simply return true. * \return false, if a top-level conflict is detected. Otherwise, true. */ bool simplify(); //! Shuffle constraints upon next simplification. void shuffleOnNextSimplify(){ shufSimp_ = 1; } //! Removes all conditional knowledge, i.e. all previously tagged learnt clauses. /*! * \see Solver::pushTagVar() */ void removeConditional(); //! Resolves all tagged clauses with the tag literal and thereby strengthens the learnt db. /*! * \see Solver::pushTagVar() */ void strengthenConditional(); //! Sets the literal p to true and schedules p for propagation. /*! * Setting a literal p to true means assigning the appropriate value to * p's variable. That is: value_false if p is a negative literal and value_true * if p is a positive literal. * \param p The literal that should become true. * \param a The reason for the literal to become true or 0 if no reason exists. * * \return * - false if p is already false * - otherwise true. * * \pre hasConflict() == false * \pre a.isNull() == false || decisionLevel() <= rootLevel() || searchMode() == no_learning * \post * p.var() == trueValue(p) || p.var() == falseValue(p) && hasConflict() == true * * \note if setting p to true leads to a conflict, the nogood that caused the * conflict can be requested using the conflict() function. */ bool force(const Literal& p, const Antecedent& a) { assert(!hasConflict() || isTrue(p)); if (assign_.assign(p, decisionLevel(), a)) return true; setConflict(p, a, UINT32_MAX); return false; } /*! * \overload bool Solver::force(const Literal&, const Antecedent&) */ bool force(const Literal& p, const Antecedent& a, uint32 data) { return data != UINT32_MAX ? assign_.assign(p, decisionLevel(), a.constraint(), data) || (setConflict(p, a, data), false) : force(p, a); } //! Assigns p at dl because of r. /*! * \pre dl <= decisionLevel() * \note * If dl < ul = max(rootLevel(), backtrackLevel()), p is actually assigned * at ul but the solver stores enough information to reassign * p on backtracking. */ bool force(Literal p, uint32 dl, const Antecedent& r, uint32 d = UINT32_MAX) { return dl == decisionLevel() ? force(p, r, d) : force(ImpliedLiteral(p, dl, r, d)); } //! Assigns p as a fact at decision level 0. bool force(Literal p) { return force(p, 0, Antecedent(lit_true())); } //! Assumes the literal p if possible. /*! * If p is currently unassigned, sets p to true and starts a new decision level. * \pre validVar(p.var()) == true * \param p The literal to assume. * \return !isFalse(p) */ bool assume(const Literal& p); //! Selects and assumes the next branching literal by calling the installed decision heuristic. /*! * \pre queueSize() == 0 * \note The next decision literal will be selected randomly with probability f. * \return * - true if the assignment is not total and a literal was assumed (or forced). * - false otherwise * . * \see DecisionHeuristic */ bool decideNextBranch(double f = 0.0); //! Sets a conflict that forces the solver to terminate its search. /*! * \pre !hasConflict() * \post hasConflict() * * \note * To prevent the solver from resolving the stop conflict, the * function sets the root level to the current decision level. * Call clearStopConflict() to remove the conflict and to restore * the previous root-level. */ void setStopConflict(); /*! * Propagates all enqueued literals. If a conflict arises during propagation * propagate returns false and the current conflict (as a set of literals) * is stored in the solver's conflict variable. * \pre !hasConflict() * \see Solver::force * \see Solver::assume * \note Shall not be called recursively. */ bool propagate(); /*! * Does unit propagation and calls x->propagateFixpoint(*this) * for all post propagators x up to but not including p. * \note The function is meant to be called only in the context of p. * \pre p is a post propagator of this solver, i.e. was previously added via addPost(). * \pre Post propagators are active, i.e. the solver is fully initialized. */ bool propagateUntil(PostPropagator* p); //! Executes a one-step lookahead on p. /*! * Assumes p and propagates this assumption. If propagations leads to * a conflict, false is returned. Otherwise the assumption is undone and * the function returns true. * \param p The literal to test. * \param c The constraint that wants to test p (can be 0). * \pre p is free * \note If c is not null and testing p does not lead to a conflict, * c->undoLevel() is called *before* p is undone. Hence, the * range [s.levelStart(s.decisionLevel()), s.assignment().size()) * contains p followed by all literals that were forced because of p. * \note propagateUntil(c) is used to propagate p. */ bool test(Literal p, PostPropagator* c); //! Estimates the number of assignments following from setting p to true. /*! * \note For the estimate only binary clauses are considered. */ uint32 estimateBCP(const Literal& p, int maxRecursionDepth = 5) const; //! Computes the number of in-edges for each assigned literal. /*! * \pre !hasConflict() * \note For a literal p assigned on level level(p), only in-edges from * levels < level(p) are counted. * \return The maximum number of in-edges. */ uint32 inDegree(WeightLitVec& out); struct DBInfo { uint32 size; uint32 locked; uint32 pinned; }; //! Removes upto remMax percent of the learnt nogoods. /*! * \param remMax Fraction of nogoods to remove ([0.0,1.0]). * \param rs Strategy to apply during nogood deletion. * \return The number of locked and active/glue clauses currently exempt from deletion. * \note * Nogoods that are the reason for a literal to be in the assignment * are said to be locked and won't be removed. */ DBInfo reduceLearnts(float remMax, const ReduceStrategy& rs = ReduceStrategy()); //! Resolves the active conflict using the selected strategy. /*! * If searchMode() is set to learning, resolveConflict implements * First-UIP learning and backjumping. Otherwise, it simply applies * chronological backtracking. * \pre hasConflict() * \return * - true if the conflict was successfully resolved * - false otherwise * \note * If decisionLevel() == rootLevel() false is returned. */ bool resolveConflict(); //! Backtracks the last decision and updates the backtrack-level if necessary. /*! * \return * - true if backtracking was possible * - false if decisionLevel() == rootLevel() */ bool backtrack(); //! Undoes all assignments up to (but not including) decision level dl. /*! * \post decision level == max(min(decisionLevel(), dl), max(rootLevel(), backtrackLevel())) * \return The decision level after undoing assignments. * \note * undoUntil() stops at the current backtrack level unless undoMode includes the mode * that was used when setting the backtrack level. * \note * If undoMode contains undo_save_phases, the functions saves the values of variables that are undone. * Otherwise, phases are only saved if indicated by the active strategy. */ uint32 undoUntil(uint32 dl, uint32 undoMode); //! Behaves like undoUntil(dl, undo_default). uint32 undoUntil(uint32 dl) { return undoUntilImpl(dl, false); } //! Returns whether undoUntil(decisionLevel()-1) is valid and would remove decisionLevel(). bool isUndoLevel() const; //! Adds a new auxiliary variable to this solver. /*! * Auxiliary variables are local to one solver and are not considered * as part of the problem. They shall be added/used only during solving, i.e. * after problem setup is completed. */ Var pushAuxVar(); //! Pops the num most recently added auxiliary variables and destroys all constraints in auxCons. void popAuxVar(uint32 num = UINT32_MAX, ConstraintDB* auxCons = 0); //@} /*! * \name State inspection * Functions for inspecting the state of the solver & search. * \note validVar(v) is a precondition for all functions that take a variable as * parameter. * @{ */ //! Returns the number of problem variables. uint32 numProblemVars() const { return shared_->numVars(); } //! Returns the number of active solver-local aux variables. uint32 numAuxVars() const { return numVars() - numProblemVars(); } //! Returns the number of solver variables, i.e. numProblemVars() + numAuxVars() uint32 numVars() const { return assign_.numVars() - 1; } //! Returns true if var represents a valid variable in this solver. bool validVar(Var var) const { return var <= numVars(); } //! Returns true if var is a solver-local aux var. bool auxVar(Var var) const { return shared_->numVars() < var; } //! Returns the number of assigned variables. uint32 numAssignedVars() const { return assign_.assigned(); } //! Returns the number of free variables. /*! * The number of free variables is the number of vars that are neither * assigned nor eliminated. */ uint32 numFreeVars() const { return assign_.free()-1; } //! Returns the value of v w.r.t the current assignment. ValueRep value(Var v) const { assert(validVar(v)); return assign_.value(v); } //! Returns the value of v w.r.t the top level. ValueRep topValue(Var v) const { return level(v) == 0 ? value(v) : value_free; } //! Returns the set of preferred values of v. ValueSet pref(Var v) const { assert(validVar(v)); return assign_.pref(v);} //! Returns true if p is true w.r.t the current assignment. bool isTrue(Literal p) const { assert(validVar(p.var())); return assign_.value(p.var()) == trueValue(p); } //! Returns true if p is false w.r.t the current assignment. bool isFalse(Literal p) const { assert(validVar(p.var())); return assign_.value(p.var()) == falseValue(p); } //! Returns the literal of v being true in the current assignment. /*! * \pre v is assigned a value in the current assignment */ Literal trueLit(Var v) const { assert(value(v) != value_free); return Literal(v, valSign(value(v))); } Literal defaultLit(Var v) const; //! Returns the decision level on which v was assigned. /*! * \note The returned value is only meaningful if value(v) != value_free. */ uint32 level(Var v) const { assert(validVar(v)); return assign_.level(v); } //! Returns true if v is currently marked as seen. /*! * Note: variables assigned on level 0 are always marked. */ bool seen(Var v) const { assert(validVar(v)); return assign_.seen(v, 3u); } //! Returns true if the literal p is currently marked as seen. bool seen(Literal p) const { assert(validVar(p.var())); return assign_.seen(p.var(), uint8(1+p.sign())); } //! Returns the current decision level. uint32 decisionLevel() const { return (uint32)levels_.size(); } bool validLevel(uint32 dl) const { return dl != 0 && dl <= decisionLevel(); } //! Returns the starting position of decision level dl in the trail. /*! * \pre validLevel(dl) */ uint32 levelStart(uint32 dl) const { assert(validLevel(dl)); return levels_[dl-1].trailPos; } //! Returns the decision literal of the decision level dl. /*! * \pre validLevel(dl) */ Literal decision(uint32 dl) const { assert(validLevel(dl)); return assign_.trail[ levels_[dl-1].trailPos ]; } //! Returns true, if the current assignment is conflicting. bool hasConflict() const { return !conflict_.empty(); } bool hasStopConflict() const { return hasConflict() && conflict_[0] == lit_false(); } //! Returns the number of (unprocessed) literals in the propagation queue. uint32 queueSize() const { return (uint32) assign_.qSize(); } //! Number of problem constraints in this solver. uint32 numConstraints() const; //! Returns the number of constraints that are currently in the solver's learnt database. uint32 numLearntConstraints() const { return (uint32)learnts_.size(); } //! Returns the reason for p being true. /*! * \pre p is true w.r.t the current assignment */ const Antecedent& reason(Literal p) const { assert(isTrue(p)); return assign_.reason(p.var()); } //! Returns the additional reason data associated with p. uint32 reasonData(Literal p) const { return assign_.data(p.var()); } //! Returns the current (partial) assignment as a set of true literals. /*! * \note Although the special var 0 always has a value it is not considered to be * part of the assignment. */ const LitVec& trail() const { return assign_.trail; } const Assignment& assignment() const { return assign_; } //! Returns the current conflict as a set of literals. const LitVec& conflict() const { return conflict_; } //! Returns the most recently derived conflict clause. const LitVec& conflictClause() const { return cc_; } //! Returns the set of eliminated literals that are unconstraint w.r.t the last model. const LitVec& symmetric() const { return temp_; } //! Returns the enumeration constraint set by the enumerator used. Constraint* enumerationConstraint() const { return enum_; } DBRef constraints() const { return constraints_; } //! Returns the idx'th learnt constraint. /*! * \pre idx < numLearntConstraints() */ Constraint& getLearnt(uint32 idx) const { assert(idx < numLearntConstraints()); return *learnts_[ idx ]; } mutable RNG rng; //!< Random number generator for this object. ValueVec model; //!< Stores the last model (if any). LowerBound lower; //!< Stores the last lower bound found (if any). SolverStats stats; //!< Stores statistics about the solving process. //@} /*! * \name Watch management * Functions for setting/removing watches. * \pre validVar(v) * @{ */ //! Returns the number of constraints watching the literal p. uint32 numWatches(Literal p) const; //! Returns true if the constraint c watches the literal p. bool hasWatch(Literal p, Constraint* c) const; bool hasWatch(Literal p, ClauseHead* c) const; //! Returns c's watch-structure associated with p. /*! * \note returns 0, if hasWatch(p, c) == false */ GenericWatch* getWatch(Literal p, Constraint* c) const; //! Adds c to the watch-list of p. /*! * When p becomes true, c->propagate(p, data, *this) is called. * \post hasWatch(p, c) == true */ void addWatch(Literal p, Constraint* c, uint32 data = 0) { assert(validWatch(p)); watches_[p.id()].push_right(GenericWatch(c, data)); } //! Adds w to the clause watch-list of p. void addWatch(Literal p, const ClauseWatch& w) { assert(validWatch(p)); watches_[p.id()].push_left(w); } //! Removes c from p's watch-list. /*! * \post hasWatch(p, c) == false */ void removeWatch(const Literal& p, Constraint* c); void removeWatch(const Literal& p, ClauseHead* c); //! Adds c to the watch-list of decision-level dl. /*! * Constraints in the watch-list of a decision level are * notified when that decision level is about to be backtracked. * \pre validLevel(dl) */ void addUndoWatch(uint32 dl, Constraint* c) { assert(validLevel(dl)); if (levels_[dl-1].undo != 0) { levels_[dl-1].undo->push_back(c); } else { levels_[dl-1].undo = allocUndo(c); } } //! Removes c from the watch-list of the decision level dl. bool removeUndoWatch(uint32 dl, Constraint* c); //@} /*! * \name Misc functions * Low-level implementation functions. Use with care and only if you * know what you are doing! * @{ */ bool addPost(PostPropagator* p, bool init); //! Updates the reason for p being true. /*! * \pre p is true and x is a valid reason for p */ bool setReason(Literal p, const Antecedent& x, uint32 data = UINT32_MAX) { assert(isTrue(p) || shared_->eliminated(p.var())); assign_.setReason(p.var(), x); if (data != UINT32_MAX) { assign_.setData(p.var(), data); } return true; } void setPref(Var v, ValueSet::Value which, ValueRep to) { assert(validVar(v) && to <= value_false); assign_.requestPrefs(); assign_.setPref(v, which, to); } void resetPrefs() { assign_.resetPrefs(); } void resetLearntActivities(); //! Returns the reason for p being true as a set of literals. void reason(Literal p, LitVec& out) { assert(isTrue(p)); out.clear(); return assign_.reason(p.var()).reason(*this, p, out); } //! Helper function for updating antecedent scores during conflict resolution. /*! * \param sc The current score of the active antecedent. * \param p The literal implied by the active antecedent. * \param lits The literals of the active antecedent. * \return true if a score was updated. * * \note Depending on the active solver strategies, the function * increases the activity and/or updates the lbd of the given antecedent. * * \note If SolverStrategies::bumpVarAct is active, p's activity * is increased if the new lbd is smaller than the lbd of the * conflict clause that is currently being derived. */ bool updateOnReason(ConstraintScore& sc, Literal p, const LitVec& lits) { // update only during conflict resolution if (&lits != &conflict_) { return false; } sc.bumpActivity(); uint32 up = strategy_.updateLbd; if (up != SolverStrategies::lbd_fixed && !lits.empty()) { uint32 lbd = sc.lbd(); uint32 inc = uint32(up != SolverStrategies::lbd_updated_less); uint32 nLbd = countLevels(&lits[0], &lits[0] + lits.size(), lbd - inc); if ((nLbd + inc) < lbd) { sc.bumpLbd(nLbd + uint32(up == SolverStrategies::lbd_update_pseudo)); } } if (strategy_.bumpVarAct && isTrue(p)) { bumpAct_.push_back(WeightLiteral(p, sc.lbd())); } return true; } //! Helper function for increasing antecedent activities during conflict clause minimization. bool updateOnMinimize(ConstraintScore& sc) { return !strategy_.ccMinKeepAct && (sc.bumpActivity(), true); } //! Helper function for antecedents to be called during conflict clause minimization. bool ccMinimize(Literal p, CCMinRecursive* rec) const { return seen(p.var()) || (rec && hasLevel(level(p.var())) && ccMinRecurse(*rec, p)); } //! Allocates a small block (32-bytes) from the solver's small block pool. void* allocSmall() { return smallAlloc_.allocate(); } //! Frees a small block previously allocated from the solver's small block pool. void freeSmall(void* m) { smallAlloc_.free(m); } void addLearntBytes(uint32 bytes) { memUse_ += bytes; } void freeLearntBytes(uint64 bytes) { memUse_ -= (bytes < memUse_) ? bytes : memUse_; } bool restartReached(const SearchLimits& limit) const; bool reduceReached(const SearchLimits& limit) const; //! simplifies cc and returns finalizeConflictClause(cc, info); uint32 simplifyConflictClause(LitVec& cc, ConstraintInfo& info, ClauseHead* rhs); uint32 finalizeConflictClause(LitVec& cc, ConstraintInfo& info, uint32 ccRepMode = 0); uint32 countLevels(const Literal* first, const Literal* last, uint32 maxLevels = Clasp::LBD_MAX); bool hasLevel(uint32 dl) const { assert(validLevel(dl)); return levels_[dl-1].marked != 0; } bool frozenLevel(uint32 dl) const { assert(validLevel(dl)); return levels_[dl-1].freeze != 0; } bool inputVar(Literal p) const { return varInfo(p.var()).input(); } void markLevel(uint32 dl) { assert(validLevel(dl)); levels_[dl-1].marked = 1; } void freezeLevel(uint32 dl) { assert(validLevel(dl)); levels_[dl-1].freeze = 1; } void unmarkLevel(uint32 dl) { assert(validLevel(dl)); levels_[dl-1].marked = 0; } void unfreezeLevel(uint32 dl){ assert(validLevel(dl)); levels_[dl-1].freeze = 0; } void markSeen(Var v) { assert(validVar(v)); assign_.setSeen(v, 3u); } void markSeen(Literal p) { assert(validVar(p.var())); assign_.setSeen(p.var(), uint8(1+p.sign())); } void clearSeen(Var v) { assert(validVar(v)); assign_.clearSeen(v); } void setHeuristic(DecisionHeuristic* h, Ownership_t::Type own); void destroyDB(ConstraintDB& db); SolverStrategies& strategies() { return strategy_; } bool resolveToFlagged(const LitVec& conflictClause, uint8 vflag, LitVec& out, uint32& lbd) const; void resolveToCore(LitVec& out); //@} private: struct DLevel { explicit DLevel(uint32 pos = 0, ConstraintDB* u = 0) : trailPos(pos) , marked(0) , freeze(0) , undo(u) {} uint32 trailPos : 30; uint32 marked : 1; uint32 freeze : 1; ConstraintDB* undo; }; struct DecisionLevels : public PodVector::type { DecisionLevels() : root(0), flip(0), mode(0), jump(0) {} uint32 root; // root level uint32 flip : 30; // backtrack level uint32 mode : 2; // type of backtrack level uint32 jump; // length of active undo }; typedef PodVector::type ReasonVec; typedef PodVector::type Watches; struct Dirty; struct CmpScore { typedef std::pair ViewPair; CmpScore(const ConstraintDB& learnts, ReduceStrategy::Score sc, uint32 g, uint32 f = 0) : db(learnts), rs(sc), glue(g), freeze(f) {} uint32 score(const ConstraintScore& act) const { return ReduceStrategy::asScore(rs, act); } bool operator()(uint32 lhsId, uint32 rhsId) const { return (*this)(db[lhsId], db[rhsId]); } bool operator()(const ViewPair& lhs, const ViewPair& rhs) const { return this->operator()(lhs.second, rhs.second); } bool operator()(ConstraintScore lhs, ConstraintScore rhs) const { return ReduceStrategy::compare(rs, lhs, rhs) < 0;} bool operator()(const Constraint* lhs, const Constraint* rhs) const { return this->operator()(lhs->activity(), rhs->activity()); } bool isFrozen(const ConstraintScore& a) const { return a.bumped() && a.lbd() <= freeze; } bool isGlue(const ConstraintScore& a) const { return a.lbd() <= glue; } const ConstraintDB& db; ReduceStrategy::Score rs; uint32 glue; uint32 freeze; private: CmpScore& operator=(const CmpScore&); }; bool validWatch(Literal p) const { return p.id() < (uint32)watches_.size(); } void freeMem(); void resetHeuristic(Solver* detach, DecisionHeuristic* h = 0, Ownership_t::Type own = Ownership_t::Acquire); bool simplifySAT(); bool unitPropagate(); bool postPropagate(PostPropagator* stop); void cancelPropagation(); uint32 undoUntilImpl(uint32 dl, bool sp); void undoLevel(bool sp); uint32 analyzeConflict(); bool isModel(); bool resolveToFlagged(const LitVec& conflictClause, uint8 vf, LitVec& out, uint32& lbd); void otfs(Antecedent& lhs, const Antecedent& rhs, Literal p, bool final); ClauseHead* otfsRemove(ClauseHead* c, const LitVec* newC); uint32 ccMinimize(LitVec& cc, LitVec& removed, uint32 antes, CCMinRecursive* ccMin); void ccMinRecurseInit(CCMinRecursive& ccMin); bool ccMinRecurse(CCMinRecursive& ccMin, Literal p) const; bool ccRemovable(Literal p, uint32 antes, CCMinRecursive* ccMin); Antecedent ccHasReverseArc(Literal p, uint32 maxLevel, uint32 maxNew); void ccResolve(LitVec& cc, uint32 pos, const LitVec& reason); void undoFree(ConstraintDB* x); void setConflict(Literal p, const Antecedent& a, uint32 data); bool force(const ImpliedLiteral& p); void updateBranch(uint32 n); uint32 incEpoch(uint32 size, uint32 inc = 1); DBInfo reduceLinear(uint32 maxR, const CmpScore& cmp); DBInfo reduceSort(uint32 maxR, const CmpScore& cmp); DBInfo reduceSortInPlace(uint32 maxR, const CmpScore& cmp, bool onlyPartialSort); Literal popVars(uint32 num, bool popLearnt, ConstraintDB* popAux); ConstraintDB* allocUndo(Constraint* c); SharedContext* shared_; // initialized by master thread - otherwise read-only! SolverStrategies strategy_; // strategies used by this object HeuristicPtr heuristic_; // active decision heuristic CCMinRecursive* ccMin_; // additional data for supporting recursive strengthen PostPropagator** postHead_; // head of post propagator list to propagate ConstraintDB* undoHead_; // free list of undo DBs Constraint* enum_; // enumeration constraint - set by enumerator uint64 memUse_; // memory used by learnt constraints (estimate) Dirty* lazyRem_; // set of watch lists that contain invalid constraints SmallClauseAlloc smallAlloc_; // allocator object for small clauses Assignment assign_; // three-valued assignment. DecisionLevels levels_; // information (e.g. position in trail) on each decision level ConstraintDB constraints_; // problem constraints ConstraintDB learnts_; // learnt constraints PropagatorList post_; // (possibly empty) list of post propagators Watches watches_; // for each literal p: list of constraints watching p LitVec conflict_; // conflict-literals for later analysis LitVec cc_; // temporary: conflict clause within analyzeConflict LitVec temp_; // temporary: redundant literals in simplifyConflictClause WeightLitVec bumpAct_; // temporary: lits from current dl whose activity might get an extra bump VarVec epoch_; // temporary vector for computing LBD VarVec cflStamp_; // temporary vector for computing number of conflicts in branch ImpliedList impliedLits_; // lits that were asserted on current dl but are logically implied earlier ConstraintInfo ccInfo_; // temporary: information about conflict clause cc_ Literal tag_; // aux literal for tagging learnt constraints uint32 dbIdx_; // position of first new problem constraint in master db uint32 lastSimp_ :30;// number of top-level assignments on last call to simplify uint32 shufSimp_ : 1;// shuffle db on next simplify? uint32 initPost_ : 1;// initialize new post propagators? }; inline bool isRevLit(const Solver& s, Literal p, uint32 maxL) { return s.isFalse(p) && (s.seen(p) || s.level(p.var()) < maxL); } //! Simplifies the constraints in db and removes those that are satisfied. template void simplifyDB(Solver& s, C& db, bool shuffle) { typename C::size_type j = 0; for (typename C::size_type i = j, end = db.size(); i != end; ++i) { Constraint* c = db[i]; if (c->simplify(s, shuffle)){ c->destroy(&s, false); } else { db[j++] = c; } } shrinkVecTo(db, j); } //! Destroys (and optionally detaches) all constraints in db. void destroyDB(Solver::ConstraintDB& db, Solver* s, bool detach); //! Returns the default decision literal of the given variable. inline Literal Solver::defaultLit(Var v) const { switch(strategy_.signDef) { default: // case SolverStrategies::sign_atom: return Literal(v, !varInfo(v).has(VarInfo::Body)); case SolverStrategies::sign_pos : return posLit(v); case SolverStrategies::sign_neg : return negLit(v); case SolverStrategies::sign_rnd : return Literal(v, rng.drand() < 0.5); } } //! Event type optionally emitted after a conflict. struct NewConflictEvent : SolveEvent { NewConflictEvent(const Solver& s, const LitVec& c, const ConstraintInfo& i) : SolveEvent(s, verbosity_quiet), learnt(&c), info(i) {} const LitVec* learnt; //!< Learnt conflict clause. ConstraintInfo info; //!< Additional information associated with the conflict clause. }; //@} /** * \defgroup heuristic Decision Heuristics * \brief Decision heuristics and related classes. * \ingroup solver */ //@{ //! Base class for decision heuristics to be used in a Solver. /*! * During search the decision heuristic is used whenever the DPLL-procedure must pick * a new variable to branch on. Each concrete decision heuristic can implement a * different algorithm for selecting the next decision variable. */ class DecisionHeuristic { public: DecisionHeuristic() {} virtual ~DecisionHeuristic(); /*! * Called once after all problem variables are known to the solver. * The default-implementation is a noop. * \param s The solver in which this heuristic is used. */ virtual void startInit(const Solver& s) { (void)s; } /*! * Called once after all problem constraints are known to the solver * and the problem was simplified. * The default-implementation is a noop. * \param s The solver in which this heuristic is used. */ virtual void endInit(Solver& s) { (void)s; } //! Called once if s switches to a different heuristic. virtual void detach(Solver& s) { (void)s; } //! Called if configuration has changed. virtual void setConfig(const HeuParams& p) { (void)p; } /*! * Called if the state of one or more variables changed. * A state change is one of: * - A previously eliminated variable is resurrected. * - A new aux variable was added. * - An aux variable was removed. * . * \param s Solver in which the state change occurred. * \param v The first variable affected by the change. * \param n The range of variables affected, i.e. [v, v+n). * \note Use s.validVar(v) and s.auxVar(v) to determine the reason for the update. */ virtual void updateVar(const Solver& s, Var v, uint32 n) = 0; /*! * Called on decision level 0. Variables that are assigned on this level * may be removed from any decision heuristic. * \note Whenever the solver returns to dl 0, simplify is only called again * if the solver learnt new facts since the last call to simplify. * * \param s The solver that reached decision level 0. * \param st The position in the trail of the first new learnt fact. */ virtual void simplify(const Solver& s, LitVec::size_type st) { (void)s; (void)st; } /*! * Called whenever the solver backracks. * Literals in the range [s.trail()[st], s.trail().size()) are subject to backtracking. * The default-implementation is a noop. * \param s The solver that is about to backtrack. * \param st Position in the trail of the first literal that will be backtracked. */ virtual void undoUntil(const Solver& s, LitVec::size_type st) { (void)s; (void)st; } /*! * Called whenever a new constraint is added to the solver s. * The default-implementation is a noop. * \param s The solver to which the constraint is added. * \param first First literal of the new constraint. * \param size Size of the new constraint. * \param t Type of the new constraint. * \note first points to an array of size size. */ virtual void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t) { (void)s; (void)first; (void)size; (void)t; } /*! * Called for each new reason-set that is traversed during conflict analysis. * The default-implementation is a noop. * \param s The solver in which the conflict is analyzed. * \param lits The current reason-set under inspection. * \param resolveLit The literal that is currently resolved. * \note When a conflict is detected, the solver passes the conflicting literals * in lits during the first call to updateReason. On that first call resolveLit * is the sentinel-literal. */ virtual void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit) { (void)s; (void)lits; (void)resolveLit; } //! Shall bump the activity of literals in lits by lits.second * adj. /*! * The default-implementation is a noop and always returns false. * \return true if heuristic supports activities, false otherwise. */ virtual bool bump(const Solver& s, const WeightLitVec& lits, double adj) { (void)s; (void)lits; (void)adj; return false; } /*! * Called whenever the solver must pick a new variable to branch on. * \param s The solver that needs a new decision variable. * \return * - true : if the decision heuristic assumed a literal * - false : if no decision could be made because assignment is total or there is a conflict * . * \post * If true is returned, the heuristic has asserted a literal. */ bool select(Solver& s) { return s.numFreeVars() != 0 && s.assume(doSelect(s)); } //! Implements the actual selection process. /*! * \pre s.numFreeVars() > 0, i.e. there is at least one variable to branch on. * \return * - a literal that is currently free or * - a sentinel literal. In that case, the heuristic shall have asserted a literal! */ virtual Literal doSelect(Solver& s) = 0; /*! * Shall select one of the literals in the range [first, last). * \param s The solver that needs a new decision variable. * \param first Pointer to first literal in range. * \param last Pointer to the end of the range. * \pre [first, last) is not empty and all literals in the range are currently unassigned. * \note The default implementation returns *first. */ virtual Literal selectRange(Solver& s, const Literal* first, const Literal* last) { (void)s; (void)last; return *first; } static Literal selectLiteral(Solver& s, Var v, int signScore) { ValueSet prefs = s.pref(v); if (signScore != 0 && !prefs.has(ValueSet::user_value | ValueSet::saved_value | ValueSet::pref_value)) { return Literal(v, signScore < 0); } else if (!prefs.empty()) { return Literal(v, prefs.sign()); } return s.defaultLit(v); } private: DecisionHeuristic(const DecisionHeuristic&); DecisionHeuristic& operator=(const DecisionHeuristic&); }; //! Selects the first free literal w.r.t to the initial variable order. class SelectFirst : public DecisionHeuristic { public: void updateVar(const Solver&, Var, uint32) {} protected: Literal doSelect(Solver& s); }; //@} } #endif clingo-5.2.2/clasp/clasp/solver_strategies.h000066400000000000000000000705261320011352300211140ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_SOLVER_STRATEGIES_H_INCLUDED #define CLASP_SOLVER_STRATEGIES_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #if !defined(CLASP_ALIGN_BITFIELD) # if defined(EMSCRIPTEN) // Force alignment of bitfield to T in order to prevent // code-generation bug in emcc // see: https://github.com/kripken/emscripten/issues/4540 # define CLASP_ALIGN_BITFIELD(T) T : 0; # else # define CLASP_ALIGN_BITFIELD(T) # endif #endif /*! * \file * \brief Contains strategies and options used to configure solvers and search. */ namespace Clasp { //! Implements clasp's configurable schedule-strategies. /*! * clasp currently supports the following basic strategies: * - geometric sequence : X = n1 * n2^k (k >= 0) * - arithmetic sequence : X = n1 + (n2*k) (k >= 0) * - fixed sequence : X = n1 + (0*k) (k >= 0) * - luby's sequence : X = n1 * luby(k)(k >= 0) * . * Furthermore, an inner-outer scheme can be applied to the selected sequence. * In that case, the sequence is repeated every \+j restarts, where * \ is the initial outer-limit and j is the number of times the * sequence was already repeated. * * \note For luby's seqeuence, j is not a repetition counter * but the index where the sequence grows to the next power of two. * * \see Luby et al. "Optimal speedup of las vegas algorithms." * */ struct ScheduleStrategy { public: //! Supported strategies. enum Type { Geometric = 0, Arithmetic = 1, Luby = 2, User = 3 }; ScheduleStrategy(Type t = Geometric, uint32 b = 100, double g = 1.5, uint32 o = 0); //! Creates luby's sequence with unit-length unit and optional outer limit. static ScheduleStrategy luby(uint32 unit, uint32 limit = 0) { return ScheduleStrategy(Luby, unit, 0, limit); } //! Creates geometric sequence base * (grow^k) with optional outer limit. static ScheduleStrategy geom(uint32 base, double grow, uint32 limit = 0) { return ScheduleStrategy(Geometric, base, grow, limit); } //! Creates arithmetic sequence base + (add*k) with optional outer limit. static ScheduleStrategy arith(uint32 base, double add, uint32 limit = 0) { return ScheduleStrategy(Arithmetic, base, add, limit); } //! Creates fixed sequence with length base. static ScheduleStrategy fixed(uint32 base) { return ScheduleStrategy(Arithmetic, base, 0, 0); } static ScheduleStrategy none() { return ScheduleStrategy(Geometric, 0); } static ScheduleStrategy def() { return ScheduleStrategy(User, 0, 0.0); } uint64 current() const; bool disabled() const { return base == 0; } bool defaulted()const { return base == 0 && type == User; } void reset() { idx = 0; } uint64 next(); void advanceTo(uint32 idx); uint32 base : 30; // base of sequence (n1) uint32 type : 2; // type of basic sequence uint32 idx; // current index into sequence uint32 len; // length of sequence (0 if infinite) (once reached, sequence is repeated and len increased) float grow; // update parameter n2 }; //! Returns the idx'th value of the luby sequence. uint32 lubyR(uint32 idx); //! Returns the idx'th value of the geometric sequence with the given growth factor. double growR(uint32 idx, double g); //! Returns the idx'th value of the arithmetic sequence with the given addend. double addR(uint32 idx, double a); class DecisionHeuristic; //! Parameter-Object for grouping solver strategies. struct SolverStrategies { //! Clasp's two general search strategies. enum SearchStrategy { use_learning = 0, //!< Analyze conflicts and learn First-1-UIP-clause. no_learning = 1 //!< Don't analyze conflicts - chronological backtracking. }; //! Default sign heuristic. enum SignHeu { sign_atom = 0, //!< Prefer negative literal for atoms. sign_pos = 1, //!< Prefer positive literal. sign_neg = 2, //!< Prefer negative literal. sign_rnd = 3, //!< Prefer random literal. }; //! Conflict clause minimization strategy. enum CCMinType { cc_local = 0, //!< Basic algorithm. cc_recursive = 1, //!< Extended algorithm. }; //! Antecedents to consider during conflict clause minimization. enum CCMinAntes { all_antes = 0, //!< Consider all antecedents. short_antes = 1, //!< Consider only short antecedents. binary_antes = 2, //!< Consider only binary antecedents. no_antes = 3, //!< Don't minimize conflict clauses. }; //! Simplifications for long conflict clauses. enum CCRepMode { cc_no_replace = 0,//!< Don't replace literals in conflict clauses. cc_rep_decision= 1,//!< Replace conflict clause with decision sequence. cc_rep_uip = 2,//!< Replace conflict clause with all uip clause. cc_rep_dynamic = 3,//!< Dynamically select between cc_rep_decision and cc_rep_uip. }; //! Strategy for initializing watched literals in clauses. enum WatchInit { watch_rand = 0, watch_first = 1, watch_least = 2 }; //! Strategy for integrating new information in parallel solving. enum UpdateMode { update_on_propagate = 0, update_on_conflict = 1 }; enum LbdMode { lbd_fixed = 0, lbd_updated_less = 1, lbd_update_glucose = 2, lbd_update_pseudo = 3 }; SolverStrategies(); void prepare(); //----- 32 bit ------------ uint32 compress : 16; /*!< If > 0, enable compression for learnt clauses of size > compress. */ uint32 saveProgress : 16; /*!< Enable progress saving if > 0. */ //----- 32 bit ------------ uint32 heuId : 3; /*!< Type of decision heuristic. */ uint32 reverseArcs : 2; /*!< Use "reverse-arcs" during learning if > 0. */ uint32 otfs : 2; /*!< Enable "on-the-fly" subsumption if > 0. */ uint32 updateLbd : 2; /*!< Update lbds of antecedents during conflict analysis (one of LbdMode). */ uint32 ccMinAntes : 2; /*!< Antecedents to look at during conflict clause minimization. */ uint32 ccRepMode : 2; /*!< One of CCRepMode. */ uint32 ccMinRec : 1; /*!< If 1, use more expensive recursive nogood minimization. */ uint32 ccMinKeepAct : 1; /*!< Do not increase nogood activities during nogood minimization? */ uint32 initWatches : 2; /*!< Initialize watches randomly in clauses. */ uint32 upMode : 1; /*!< One of UpdateMode. */ uint32 bumpVarAct : 1; /*!< Bump activities of vars implied by learnt clauses with small lbd. */ uint32 search : 1; /*!< Current search strategy. */ uint32 restartOnModel: 1; /*!< Do a restart after each model. */ uint32 signDef : 2; /*!< Default sign heuristic. */ uint32 signFix : 1; /*!< Disable all sign heuristics and always use default sign. */ uint32 reserved : 1; uint32 hasConfig : 1; /*!< Config applied to solver? */ uint32 id : 6; /*!< Solver id - SHALL ONLY BE SET BY Shared Context! */ }; //! Parameter-Object for grouping additional heuristic options. struct HeuParams { //! Strategy for scoring clauses not learnt by conflict analysis. enum ScoreOther { other_auto = 0u, other_no = 1u, other_loop = 2u, other_all = 3u }; //! Strategy for scoring during conflict analysis. enum Score { score_auto = 0u, score_min = 1u, score_set = 2u, score_multi_set = 3u }; //! Global preference for domain heuristic. enum DomPref { pref_atom = 0u, pref_scc = 1u, pref_hcc = 2u, pref_disj = 4u, pref_min = 8u, pref_show = 16u }; //! Global modification for domain heuristic. enum DomMod { mod_none = 0u, mod_level = 1u, mod_spos = 2u, mod_true = 3u, mod_sneg = 4u, mod_false = 5u, mod_init = 6u, mod_factor = 7u }; //! Values for dynamic decaying scheme. struct VsidsDecay { uint32 init: 10; /*!< Starting decay factor: 1/0.\. */ uint32 bump: 7; /*!< Decay decrease value : \/100. */ uint32 freq: 15; /*!< Update decay factor every \ conflicts. */ }; HeuParams(); uint32 param : 16; /*!< Extra parameter for heuristic with meaning depending on type. */ uint32 score : 2; /*!< Type of scoring during resolution. */ uint32 other : 2; /*!< Consider other learnt nogoods in heuristic. */ uint32 moms : 1; /*!< Use MOMS-score as top-level heuristic. */ uint32 nant : 1; /*!< Prefer elements in NegAnte(P). */ uint32 huang : 1; /*!< Only for Berkmin. */ uint32 acids : 1; /*!< Only for Vsids/Dom. */ uint32 domPref : 5; /*!< Default pref for doamin heuristic (set of DomPref). */ uint32 domMod : 3; /*!< Default mod for domain heuristic (one of DomMod). */ union { uint32 extra; VsidsDecay decay; /*!< Only for Vsids/Dom. */ }; }; struct OptParams { //! Strategy to use for optimization. enum Type { type_bb = 0, //!< Branch and bound based (model-guided) optimization. type_usc= 1, //!< Unsatisfiable-core based (core-guided) optimization. }; //! Algorithm for model-guided optimization. enum BBAlgo { bb_lin = 0u, //!< Linear branch and bound with fixed step of size 1. bb_hier = 1u, //!< Hierarchical branch and bound with fixed step of size 1. bb_inc = 2u, //!< Hierarchical branch and bound with increasing steps. bb_dec = 3u, //!< Hierarchical branch and bound with decreasing steps. }; //! Algorithm for core-guided optimization. enum UscAlgo { usc_oll = 0u, //!< OLL with possibly multiple cardinality constraints per core. usc_one = 1u, //!< ONE with one cardinality constraints per core. usc_k = 2u, //!< K with bounded cardinality constraints of size 2 * (K+1). usc_pmr = 3u, //!< PMRES with clauses. }; //! Additional tactics for core-guided optimization. enum UscOption { usc_disjoint = 1u, //!< Enable (disjoint) preprocessing. usc_succinct = 2u, //!< Do not add redundant constraints. usc_stratify = 4u, //!< Enable stratification for weighted optimization. }; //! Strategy for unsatisfiable-core shrinking. enum UscTrim { usc_trim_lin = 1u, //!< Shrinking with linear search SAT->UNSAT. usc_trim_inv = 2u, //!< Shrinking with inverse linear search UNSAT->SAT. usc_trim_bin = 3u, //!< Shrinking with binary search SAT->UNSAT. usc_trim_rgs = 4u, //!< Shrinking with repeated geometric sequence until UNSAT. usc_trim_exp = 5u, //!< Shrinking with exponential search until UNSAT. usc_trim_min = 6u, //!< Shrinking with linear search for subset minimal core. }; //! Heuristic options common to all optimization strategies. enum Heuristic { heu_sign = 1, //!< Use optimize statements in sign heuristic. heu_model = 2, //!< Apply model heuristic when optimizing. }; OptParams(Type st = type_bb); bool supportsSplitting() const { return type != type_usc; } bool hasOption(UscOption o) const { return (opts & uint32(o)) != 0u; } bool hasOption(Heuristic h) const { return (heus & uint32(h)) != 0u; } uint32 type : 1; /*!< Optimization strategy (see Type).*/ uint32 heus : 2; /*!< Set of Heuristic values. */ uint32 algo : 2; /*!< Optimization algorithm (see BBAlgo/UscAlgo). */ uint32 trim : 3; /*!< Unsatisfiable-core shrinking (0=no shrinking). */ uint32 opts : 4; /*!< Set of usc options. */ uint32 tLim : 5; /*!< Limit core shrinking to 2^tLim conflicts (0=no limit). */ uint32 kLim :15; /*!< Limit for algorithm K (0=dynamic limit). */ }; //! Parameter-Object for configuring a solver. struct SolverParams : SolverStrategies { //! Supported forget options. enum Forget { forget_heuristic = 1u, forget_signs = 2u, forget_activities = 4u, forget_learnts = 8u }; SolverParams(); uint32 prepare(); inline bool forgetHeuristic() const { return (forgetSet & uint32(forget_heuristic)) != 0; } inline bool forgetSigns() const { return (forgetSet & uint32(forget_signs)) != 0; } inline bool forgetActivities()const { return (forgetSet & uint32(forget_activities)) != 0; } inline bool forgetLearnts() const { return (forgetSet & uint32(forget_learnts)) != 0; } SolverParams& setId(uint32 sId) { id = sId; return *this; } HeuParams heuristic; /*!< Parameters for decision heuristic. */ OptParams opt; /*!< Parameters for optimization. */ // 64-bit uint32 seed; /*!< Seed for the random number generator. */ uint32 lookOps : 16; /*!< Max. number of lookahead operations (0: no limit). */ uint32 lookType : 2; /*!< Type of lookahead operations. */ uint32 loopRep : 2; /*!< How to represent loops? */ uint32 acycFwd : 1; /*!< Disable backward propagation in acyclicity checker. */ uint32 forgetSet : 4; /*!< What to forget on (incremental step). */ uint32 reserved : 7; }; typedef Range Range32; //! Aggregates restart-parameters to configure restarts during search. /*! * \see ScheduleStrategy */ struct RestartParams { RestartParams(); enum SeqUpdate { seq_continue = 0, seq_repeat = 1, seq_disable = 2 }; uint32 prepare(bool withLookback); void disable(); bool dynamic() const { return dynRestart != 0; } bool local() const { return cntLocal != 0; } SeqUpdate update() const { return static_cast(upRestart); } ScheduleStrategy sched; /**< Restart schedule to use. */ float blockScale; /**< Scaling factor for blocking restarts. */ uint32 blockWindow: 16; /**< Size of moving assignment average for blocking restarts (0: disable). */ uint32 blockFirst : 16; /**< Enable blocking restarts after blockFirst conflicts. */ CLASP_ALIGN_BITFIELD(uint32) uint32 counterRestart:16;/**< Apply counter implication bump every counterRestart restarts (0: disable). */ uint32 counterBump:16; /**< Bump factor for counter implication restarts. */ CLASP_ALIGN_BITFIELD(uint32) uint32 shuffle :14; /**< Shuffle program after shuffle restarts (0: disable). */ uint32 shuffleNext:14; /**< Re-Shuffle program every shuffleNext restarts (0: disable). */ uint32 upRestart : 2; /**< How to update restart sequence after a model was found (one of SeqUpdate). */ uint32 cntLocal : 1; /**< Count conflicts globally or relative to current branch? */ uint32 dynRestart : 1; /**< Dynamic restarts enabled? */ }; //! Reduce strategy used during solving. /*! * A reduce strategy mainly consists of an algorithm and a scoring scheme * for measuring "activity" of learnt constraints. */ struct ReduceStrategy { //! Reduction algorithm to use during solving. enum Algorithm { reduce_linear = 0, //!< Linear algorithm from clasp-1.3.x. reduce_stable = 1, //!< Sort constraints by score but keep order in learnt db. reduce_sort = 2, //!< Sort learnt db by score and remove fraction with lowest score. reduce_heap = 3 //!< Similar to reduce_sort but only partially sorts learnt db. }; //! Score to measure "activity" of learnt constraints. enum Score { score_act = 0, //!< Activity only: how often constraint is used during conflict analysis. score_lbd = 1, //!< Use literal block distance as activity. score_both = 2 //!< Use activity and lbd together. }; //! Strategy for estimating size of problem. enum EstimateSize { est_dynamic = 0, //!< Dynamically decide whether to use number of variables or constraints. est_con_complexity = 1, //!< Measure size in terms of constraint complexities. est_num_constraints = 2, //!< Measure size in terms of number constraints. est_num_vars = 3 //!< Measure size in terms of number variable. }; static uint32 scoreAct(const ConstraintScore& sc) { return sc.activity(); } static uint32 scoreLbd(const ConstraintScore& sc) { return uint32(LBD_MAX+1)-sc.lbd(); } static uint32 scoreBoth(const ConstraintScore& sc) { return (sc.activity()+1) * scoreLbd(sc); } static int compare(Score sc, const ConstraintScore& lhs, const ConstraintScore& rhs) { int fs = 0; if (sc == score_act) { fs = ((int)scoreAct(lhs)) - ((int)scoreAct(rhs)); } else if (sc == score_lbd) { fs = ((int)scoreLbd(lhs)) - ((int)scoreLbd(rhs)); } return fs != 0 ? fs : ((int)scoreBoth(lhs)) - ((int)scoreBoth(rhs)); } static uint32 asScore(Score sc, const Clasp::ConstraintScore& act) { if (sc == score_act) { return scoreAct(act); } if (sc == score_lbd) { return scoreLbd(act); } /* sc == score_both*/{ return scoreBoth(act);} } ReduceStrategy() : protect(0), glue(0), fReduce(75), fRestart(0), score(0), algo(0), estimate(0), noGlue(0) { static_assert(sizeof(ReduceStrategy) == sizeof(uint32), "invalid bitset"); } uint32 protect : 7; /*!< Protect nogoods whose lbd was reduced and is now <= freeze. */ uint32 glue : 4; /*!< Don't remove nogoods with lbd <= glue. */ uint32 fReduce : 7; /*!< Fraction of nogoods to remove in percent. */ uint32 fRestart: 7; /*!< Fraction of nogoods to remove on restart. */ uint32 score : 2; /*!< One of Score. */ uint32 algo : 2; /*!< One of Algorithm. */ uint32 estimate: 2; /*!< How to estimate problem size in init. */ uint32 noGlue : 1; /*!< Do not count glue clauses in limit. */ }; //! Aggregates parameters for the nogood deletion heuristic used during search. /*! * - S:delCond {yes,no} * - no:del {0}[0] * - no:del | delCond in {no} * - deletion | delCond in {yes} * - del-* | delCond in {yes} * - {delCond=yes, del-grow=no, del-cfl=no} * . */ struct ReduceParams { ReduceParams() : cflSched(ScheduleStrategy::none()), growSched(ScheduleStrategy::def()) , fInit(1.0f/3.0f) , fMax(3.0f) , fGrow(1.1f) , initRange(10, UINT32_MAX) , maxRange(UINT32_MAX) , memMax(0) {} void disable(); uint32 prepare(bool withLookback); Range32 sizeInit(const SharedContext& ctx) const; uint32 cflInit(const SharedContext& ctx) const; uint32 getBase(const SharedContext& ctx) const; float fReduce() const { return strategy.fReduce / 100.0f; } float fRestart() const { return strategy.fRestart/ 100.0f; } static uint32 getLimit(uint32 base, double f, const Range& r); ScheduleStrategy cflSched; /**< Conflict-based deletion schedule. */ ScheduleStrategy growSched; /**< Growth-based deletion schedule. */ ReduceStrategy strategy; /**< Strategy to apply during nogood deletion. */ float fInit; /**< Initial limit. X = P*fInit clamped to initRange.*/ float fMax; /**< Maximal limit. X = P*fMax clamped to maxRange. */ float fGrow; /**< Growth factor for db. */ Range32 initRange; /**< Allowed range for initial limit. */ uint32 maxRange; /**< Allowed range for maximal limit: [initRange.lo,maxRange]*/ uint32 memMax; /**< Memory limit in MB (0 = no limit). */ }; //! Parameter-Object for grouping solve-related options. /*! * \ingroup enumerator */ struct SolveParams { //! Creates a default-initialized object. /*! * The following parameters are used: * - restart : quadratic: 100*1.5^k / no restarts after first solution * - deletion : initial size: vars()/3, grow factor: 1.1, max factor: 3.0, do not reduce on restart * - randomization: disabled * - randomProp : 0.0 (disabled) * . */ SolveParams(); uint32 prepare(bool withLookback); bool randomize(Solver& s) const; RestartParams restart; ReduceParams reduce; uint32 randRuns:16; /*!< Number of initial randomized-runs. */ uint32 randConf:16; /*!< Number of conflicts comprising one randomized-run. */ float randProb; /*!< Use random heuristic with given probability ([0,1]) */ struct FwdCheck { /*!< Options for (partial checks in) DLP-solving; */ uint32 highStep : 24; /*!< Init/inc high level when reached. */ uint32 highPct : 7; /*!< Check on low + (high - low) * highPct/100 */ uint32 signDef : 2; /*!< Default sign heuristic for atoms in disjunctions. */ FwdCheck() { std::memset(this, 0, sizeof(*this)); } } fwdCheck; }; class SharedContext; class SatPreprocessor; //! Parameters for (optional) Sat-preprocessing. struct SatPreParams { enum Algo { sat_pre_no = 0, /**< Disable sat-preprocessing. */ sat_pre_ve = 1, /**< Run variable elimination. */ sat_pre_ve_bce = 2, /**< Run variable- and limited blocked clause elimination. */ sat_pre_full = 3, /**< Run variable- and full blocked clause elimination. */ }; SatPreParams() : type(0u), limIters(0u), limTime(0u), limFrozen(0u), limClause(4000u), limOcc(0u) {} uint32 type : 2; /**< One of algo. */ uint32 limIters : 11; /**< Max. number of iterations. (0=no limit)*/ uint32 limTime : 12; /**< Max. runtime in sec, checked after each iteration. (0=no limit)*/ uint32 limFrozen: 7; /**< Run only if percent of frozen vars < maxFrozen. (0=no limit)*/ uint32 limClause: 16; /**< Run only if \#clauses \< (limClause*1000) (0=no limit)*/ uint32 limOcc : 16; /**< Skip v, if \#occ(v) \>= limOcc && \#occ(~v) \>= limOcc.(0=no limit) */ bool clauseLimit(uint32 nc) const { return limClause && nc > (limClause*1000u); } bool occLimit(uint32 pos, uint32 neg) const { return limOcc && pos > (limOcc-1u) && neg > (limOcc-1u); } uint32 bce() const { return type != sat_pre_no ? type - 1 : 0; } void disableBce() { type = std::min(type, uint32(sat_pre_ve));} static SatPreprocessor* create(const SatPreParams&); }; //! Parameters for a SharedContext object. struct ContextParams { //! How to handle short learnt clauses. enum ShortMode { short_implicit = 0, /*!< Share short learnt clauses via short implication graph. */ short_explicit = 1, /*!< Do not use short implication graph. */ }; //! How to handle physical sharing of (explicit) constraints. enum ShareMode { share_no = 0, /*!< Do not physically share constraints (use copies instead). */ share_problem = 1, /*!< Share problem constraints but copy learnt constraints. */ share_learnt = 2, /*!< Copy problem constraints but share learnt constraints. */ share_all = 3, /*!< Share all constraints. */ share_auto = 4, /*!< Use share_no or share_all depending on number of solvers. */ }; ContextParams() : shareMode(share_auto), stats(0), shortMode(short_implicit), seed(1), hasConfig(0), cliConfig(0), cliId(0), cliMode(0) {} SatPreParams satPre; /*!< Preprocessing options. */ uint8 shareMode : 3; /*!< Physical sharing mode (one of ShareMode). */ uint8 stats : 2; /*!< See SharedContext::enableStats(). */ uint8 shortMode : 1; /*!< One of ShortMode. */ uint8 seed : 1; /*!< Apply new seed when adding solvers. */ uint8 hasConfig : 1; /*!< Reserved for command-line interface. */ uint8 cliConfig; /*!< Reserved for command-line interface. */ uint8 cliId; /*!< Reserved for command-line interface. */ uint8 cliMode; /*!< Reserved for command-line interface. */ }; //! Interface for configuring a SharedContext object and its associated solvers. class Configuration { public: typedef SolverParams SolverOpts; typedef SolveParams SearchOpts; typedef ContextParams CtxOpts; virtual ~Configuration(); //! Prepares this configuration for the usage in the given context. virtual void prepare(SharedContext&) = 0; //! Returns the options for the shared context. virtual const CtxOpts& context() const = 0; //! Returns the number of solver options in this config. virtual uint32 numSolver() const = 0; //! Returns the number of search options in this config. virtual uint32 numSearch() const = 0; //! Returns the solver options for the i'th solver to be attached to the SharedContext. virtual const SolverOpts& solver(uint32 i) const = 0; //! Returns the search options for the i'th solver of the SharedContext. virtual const SearchOpts& search(uint32 i) const = 0; //! Returns the heuristic to be used in the i'th solver. /*! * The function is called in Solver::startInit(). * \note The returned object is owned by the caller. */ virtual DecisionHeuristic* heuristic(uint32 i) const = 0; //! Adds post propagators to the given solver. virtual bool addPost(Solver& s) const = 0; //! Returns the configuration with the given name or 0 if no such config exists. /*! * The default implementation returns this * if n is empty or one of "." or "/". * Otherwise, 0 is returned. */ virtual Configuration* config(const char* n); }; //! Base class for user-provided configurations. class UserConfiguration : public Configuration { public: //! Adds a lookahead post propagator to the given solver if requested. /*! * The function adds a lookahead post propagator if indicated by * the solver's SolverParams. */ virtual bool addPost(Solver& s) const; //! Returns the (modifiable) solver options for the i'th solver. virtual SolverOpts& addSolver(uint32 i) = 0; //! Returns the (modifiable) search options for the i'th solver. virtual SearchOpts& addSearch(uint32 i) = 0; }; //! Simple factory for decision heuristics. struct Heuristic_t { enum Type { Default = 0, Berkmin = 1, Vsids = 2, Vmtf = 3, Domain = 4, Unit = 5, None = 6, User = 7 }; typedef DecisionHeuristic* (*Creator)(Type t, const HeuParams& p); static inline bool isLookback(uint32 type) { return type >= (uint32)Berkmin && type < (uint32)Unit; } //! Default callback for creating decision heuristics. static DecisionHeuristic* create(Type t, const HeuParams& p); }; struct ProjectMode_t { enum Mode { Implicit = 0u, Output = 1u, Explicit = 2u }; }; typedef ProjectMode_t::Mode ProjectMode; //! Basic configuration for one or more SAT solvers. class BasicSatConfig : public UserConfiguration, public ContextParams { public: typedef Heuristic_t::Creator HeuristicCreator; BasicSatConfig(); void prepare(SharedContext&); const CtxOpts& context() const { return *this; } uint32 numSolver() const { return sizeVec(solver_); } uint32 numSearch() const { return sizeVec(search_); } const SolverOpts& solver(uint32 i) const { return solver_[i % solver_.size() ]; } const SearchOpts& search(uint32 i) const { return search_[i % search_.size() ]; } DecisionHeuristic* heuristic(uint32 i) const; SolverOpts& addSolver(uint32 i); SearchOpts& addSearch(uint32 i); virtual void reset(); virtual void resize(uint32 numSolver, uint32 numSearch); //! Sets callback function for creating heuristics. void setHeuristicCreator(HeuristicCreator hc); private: typedef PodVector::type SolverVec; typedef PodVector::type SearchVec; SolverVec solver_; SearchVec search_; HeuristicCreator heu_; }; //! Base class for solving related events. template struct SolveEvent : Event_t { SolveEvent(const Solver& s, Event::Verbosity verb) : Event_t(Event::subsystem_solve, verb), solver(&s) {} const Solver* solver; }; struct Model; //! Base class for handling results of a solve operation. class ModelHandler { public: virtual ~ModelHandler(); virtual bool onModel(const Solver&, const Model&) = 0; virtual bool onUnsat(const Solver&, const Model&); }; //! Type for storing the lower bound of a minimize statement. struct LowerBound { LowerBound() : level(0), bound(CLASP_WEIGHT_SUM_MIN) {} void reset() { *this = LowerBound(); } bool active() const { return bound != CLASP_WEIGHT_SUM_MIN; } uint32 level; wsum_t bound; }; } #endif clingo-5.2.2/clasp/clasp/solver_types.h000066400000000000000000001074121320011352300201010ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_SOLVER_TYPES_H_INCLUDED #define CLASP_SOLVER_TYPES_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include #include #include /*! * \file * \brief Types and functions used by a Solver */ namespace Clasp { class SharedLiterals; /*! * \addtogroup solver */ //@{ /////////////////////////////////////////////////////////////////////////////// // SearchLimits /////////////////////////////////////////////////////////////////////////////// struct DynamicLimit; struct BlockLimit; //! Parameter-Object for managing search limits. struct SearchLimits { typedef DynamicLimit* LimitPtr; typedef BlockLimit* BlockPtr; SearchLimits(); uint64 used; struct { uint64 conflicts; //!< Soft limit on number of conflicts for restart. LimitPtr dynamic; //!< Use dynamic restarts based on lbd or conflict level. BlockPtr block; //!< Optional strategy to increase restart limit. bool local; //!< Apply conflict limit against active branch. } restart; //!< Restart limits. uint64 conflicts; //!< Soft limit on number of conflicts. uint64 memory; //!< Soft memory limit for learnt lemmas (in bytes). uint32 learnts; //!< Limit on number of learnt lemmas. }; //! Type for implementing Glucose-style dynamic restarts. /*! * \see G. Audemard, L. Simon. "Refining Restarts Strategies for SAT and UNSAT" * \note In contrast to Glucose's dynamic restarts, this class also implements * a heuristic for dynamically adjusting the margin ratio K. */ struct DynamicLimit { enum Type { lbd_limit, level_limit }; //! Creates new limit with bounded queue of the given window size. static DynamicLimit* create(uint32 window); //! Destroys this object and its bounded queue. void destroy(); //! Resets moving average and adjust limit. void init(float k, Type type, uint32 uLimit = 16000); //! Resets moving average, i.e. clears the bounded queue. void resetRun(); //! Resets moving and global average. void reset(); //! Adds an observation and updates the moving average. Typically called on conflict. void update(uint32 conflictLevel, uint32 lbd); //! Notifies this object about a restart. /*! * The function checks whether to adjust the active margin ratio and/or * whether to switch from LBD based to conflict level based restarts. * * \param maxLBD Threshold for switching between lbd and conflict level queue. * \param k Lower bound for margin ratio. */ uint32 restart(uint32 maxLBD, float k); //! Returns the number of updates since last restart. uint32 runLen() const { return num_; } //! Returns the maximal size of the bounded queue. uint32 window() const { return cap_; } //! Returns whether it is time to restart. bool reached() const { return runLen() >= window() && (sma(adjust.type) * adjust.rk) > global.avg(adjust.type); } struct { //! Returns the global lbd or conflict level average. double avg(Type t) const { return ratio(sum[t], samples); } uint64 sum[2]; //!< Sum of lbds/conflict levels since last call to resetGlobal(). uint64 samples;//!< Samples since last call to resetGlobal(). } global; //!< Global lbd/conflict level data. struct { //! Returns the average restart length, i.e. number of conflicts between restarts. double avgRestart() const { return ratio(samples, restarts); } uint32 limit; //!< Number of conflicts before an update is forced. uint32 restarts;//!< Number of restarts since last update. uint32 samples; //!< Number of samples since last update. float rk; //!< BD/CFL dynamic limit factor (typically < 1.0). Type type; //!< Dynamic limit based on lbd or confllict level. } adjust; //!< Data for dynamically adjusting margin ratio (rk). private: DynamicLimit(uint32 size); DynamicLimit(const DynamicLimit&); DynamicLimit& operator=(const DynamicLimit&); double sma(Type t) const { return sum_[t] / double(cap_); } uint32 smaU(Type t) const { return static_cast(sum_[t] / cap_); } uint64 sum_[2]; uint32 cap_; uint32 pos_; uint32 num_; POTASSCO_WARNING_BEGIN_RELAXED uint32 buffer_[0]; POTASSCO_WARNING_END_RELAXED }; //! Type for implementing Glucose-style blocking of restarts. /*! * \see G. Audemard, L. Simon "Refining Restarts Strategies for SAT and UNSAT" * \see A. Biere, A. Froehlich "Evaluating CDCL Variable Scoring Schemes" */ struct BlockLimit { explicit BlockLimit(uint32 windowSize, double R = 1.4); bool push(uint32 nAssign) { ema = n >= span ? exponentialMovingAverage(ema, nAssign, alpha) : cumulativeMovingAverage(ema, nAssign, n); return ++n >= next; } //! Returns the exponential moving average scaled by r. double scaled() const { return ema * r; } double ema; //!< Current exponential moving average. double alpha; //!< Smoothing factor: 2/(span+1). uint64 next; //!< Enable once n >= next. uint64 inc; //!< Block restart for next inc conflicts. uint64 n; //!< Number of data points seen so far. uint32 span; //!< Minimum observation window. float r; //!< Scale factor for ema. }; /////////////////////////////////////////////////////////////////////////////// // Statistics /////////////////////////////////////////////////////////////////////////////// class StatisticObject; class StatsMap; #if !defined(DOXY) #define DOXY(X) #endif #define CLASP_STAT_DEFINE(m, k, a, accu) m #define NO_ARG #define CLASP_DECLARE_ISTATS(T) \ void accu(const T& o);\ static uint32 size();\ static const char* key(uint32 i);\ StatisticObject at(const char* key) const //! A struct for holding core statistics used by a solver. /*! * Core statistics are always present in a solver and hence * can be used by heuristics. */ struct CoreStats { #define CLASP_CORE_STATS(STAT, LHS, RHS) \ STAT(uint64 choices; DOXY(number of choices) , "choices" , VALUE(choices) , LHS.choices += RHS.choices )\ STAT(uint64 conflicts; DOXY(number of conflicts) , "conflicts" , VALUE(conflicts) , LHS.conflicts += RHS.conflicts )\ STAT(uint64 analyzed; DOXY(number of conflicts analyzed), "conflicts_analyzed", VALUE(analyzed) , LHS.analyzed += RHS.analyzed )\ STAT(uint64 restarts; DOXY(number of restarts) , "restarts" , VALUE(restarts) , LHS.restarts += RHS.restarts )\ STAT(uint64 lastRestart;DOXY(length of last restart), "restarts_last" , VALUE(lastRestart), LHS.lastRestart = std::max(LHS.lastRestart, RHS.lastRestart)) CoreStats() { reset(); } void reset(); uint64 backtracks() const { return conflicts-analyzed; } uint64 backjumps() const { return analyzed; } double avgRestart() const { return ratio(analyzed, restarts); } CLASP_DECLARE_ISTATS(CoreStats); CLASP_CORE_STATS(CLASP_STAT_DEFINE, NO_ARG, NO_ARG) }; //! A struct for holding (optional) jump statistics. struct JumpStats { #define CLASP_JUMP_STATS(STAT, LHS, RHS) \ STAT(uint64 jumps; DOXY(number of backjumps) , "jumps" , VALUE(jumps) , LHS.jumps += RHS.jumps) \ STAT(uint64 bounded; DOXY(backjumps bounded by root level) , "jumps_bounded" , VALUE(bounded) , LHS.bounded += RHS.bounded) \ STAT(uint64 jumpSum; DOXY(levels removed by jumps) , "levels" , VALUE(jumpSum) , LHS.jumpSum += RHS.jumpSum) \ STAT(uint64 boundSum; DOXY(levels kept because of root level) , "levels_bounded" , VALUE(boundSum) , LHS.boundSum += RHS.boundSum) \ STAT(uint32 maxJump; DOXY(longest backjump) , "max" , VALUE(maxJump) , MAX_MEM(LHS.maxJump, RHS.maxJump)) \ STAT(uint32 maxJumpEx;DOXY(longest unbounded backjump) , "max_executed" , VALUE(maxJumpEx), MAX_MEM(LHS.maxJumpEx,RHS.maxJumpEx)) \ STAT(uint32 maxBound; DOXY(max levels kept because of root level), "max_bounded" , VALUE(maxBound) , MAX_MEM(LHS.maxBound, RHS.maxBound)) JumpStats() { reset(); } void reset(); void update(uint32 dl, uint32 uipLevel, uint32 bLevel) { ++jumps; jumpSum += dl - uipLevel; maxJump = std::max(maxJump, dl - uipLevel); if (uipLevel < bLevel) { ++bounded; boundSum += bLevel - uipLevel; maxJumpEx = std::max(maxJumpEx, dl - bLevel); maxBound = std::max(maxBound, bLevel - uipLevel); } else { maxJumpEx = maxJump; } } uint64 jumped() const { return jumpSum - boundSum; } double jumpedRatio()const { return ratio(jumped(), jumpSum); } double avgBound() const { return ratio(boundSum, bounded); } double avgJump() const { return ratio(jumpSum, jumps); } double avgJumpEx() const { return ratio(jumped(), jumps); } CLASP_DECLARE_ISTATS(JumpStats); CLASP_JUMP_STATS(CLASP_STAT_DEFINE, NO_ARG, NO_ARG) }; //! A struct for holding (optional) extended statistics. struct ExtendedStats { typedef ConstraintType type_t; //! An array for storing a value[t-1] for each learnt Constraint_t::Type t. typedef uint64 Array[Constraint_t::Type__max]; #define CLASP_EXTENDED_STATS(STAT, LHS, RHS) \ STAT(uint64 domChoices; DOXY(number of domain choices) , "domain_choices" , VALUE(domChoices) , LHS.domChoices += RHS.domChoices) \ STAT(uint64 models; DOXY(number of models) , "models" , VALUE(models) , LHS.models += RHS.models) \ STAT(uint64 modelLits; DOXY(decision levels in models) , "models_level" , VALUE(modelLits) , LHS.modelLits += RHS.modelLits) \ STAT(uint64 hccTests; DOXY(number of stability tests) , "hcc_tests" , VALUE(hccTests) , LHS.hccTests += RHS.hccTests) \ STAT(uint64 hccPartial; DOXY(number of partial tests) , "hcc_partial" , VALUE(hccPartial) , LHS.hccPartial += RHS.hccPartial) \ STAT(uint64 deleted; DOXY(lemmas deleted ) , "lemmas_deleted" , VALUE(deleted) , LHS.deleted += RHS.deleted) \ STAT(uint64 distributed;DOXY(lemmas distributed ) , "distributed" , VALUE(distributed), LHS.distributed+= RHS.distributed)\ STAT(uint64 sumDistLbd; DOXY(lbds of distributed lemmas) , "distributed_sum_lbd" , VALUE(sumDistLbd) , LHS.sumDistLbd += RHS.sumDistLbd) \ STAT(uint64 integrated; DOXY(lemmas integrated ) , "integrated" , VALUE(integrated) , LHS.integrated += RHS.integrated) \ STAT(Array learnts; DOXY(lemmas of each learnt type) , "lemmas" , MEM_FUN(lemmas) , NO_ARG) \ STAT(Array lits; DOXY(lits of each learnt type) , "lits_learnt" , MEM_FUN(learntLits), NO_ARG) \ STAT(uint32 binary; DOXY(number of binary lemmas) , "lemmas_binary" , VALUE(binary) , LHS.binary += RHS.binary) \ STAT(uint32 ternary; DOXY(number of ternary lemmas) , "lemmas_ternary" , VALUE(ternary) , LHS.ternary += RHS.ternary) \ STAT(double cpuTime; DOXY(cpu time used ) , "cpu_time" , VALUE(cpuTime) , LHS.cpuTime += RHS.cpuTime) \ STAT(uint64 intImps; DOXY(implications on integrating), "integrated_imps" , VALUE(intImps) , LHS.intImps+= RHS.intImps) \ STAT(uint64 intJumps; DOXY(backjumps on integrating) , "integrated_jumps" , VALUE(intJumps), LHS.intJumps+=RHS.intJumps) \ STAT(uint64 gpLits; DOXY(lits in received gps) , "guiding_paths_lits" , VALUE(gpLits) , LHS.gpLits += RHS.gpLits) \ STAT(uint32 gps; DOXY(guiding paths received) , "guiding_paths" , VALUE(gps) , LHS.gps += RHS.gps) \ STAT(uint32 splits; DOXY(split requests handled) , "splits" , VALUE(splits) , LHS.splits += RHS.splits) \ STAT(NO_ARG , "lemmas_conflict", VALUE(learnts[0]) , LHS.learnts[0] += RHS.learnts[0]) \ STAT(NO_ARG , "lemmas_loop" , VALUE(learnts[1]) , LHS.learnts[1] += RHS.learnts[1]) \ STAT(NO_ARG , "lemmas_other" , VALUE(learnts[2]) , LHS.learnts[2] += RHS.learnts[2]) \ STAT(NO_ARG , "lits_conflict" , VALUE(lits[0]) , LHS.lits[0] += RHS.lits[0]) \ STAT(NO_ARG , "lits_loop" , VALUE(lits[1]) , LHS.lits[1] += RHS.lits[1]) \ STAT(NO_ARG , "lits_other" , VALUE(lits[2]) , LHS.lits[2] += RHS.lits[2]) \ STAT(JumpStats jumps;DOXY(backjump statistics) , "jumps" , MAP(jumps) , LHS.jumps.accu(RHS.jumps)) ExtendedStats() { reset(); } void reset(); void addLearnt(uint32 size, type_t t) { if (t == Constraint_t::Static) return; learnts[t-1]+= 1; lits[t-1] += size; binary += (size == 2); ternary += (size == 3); } //! Total number of lemmas learnt. uint64 lemmas() const { return std::accumulate(learnts, learnts+Constraint_t::Type__max, uint64(0)); } //! Total number of literals in all learnt lemmas. uint64 learntLits() const { return std::accumulate(lits, lits+Constraint_t::Type__max, uint64(0)); } //! Number of lemmas of learnt type t. uint64 lemmas(type_t t)const { return learnts[t-1]; } //! Average length of lemmas of learnt type t. double avgLen(type_t t)const { return ratio(lits[t-1], lemmas(t)); } //! Average decision level on which models were found. double avgModel() const { return ratio(modelLits, models); } //! Ratio of lemmas that were distributed to other threads. double distRatio() const { return ratio(distributed, learnts[0] + learnts[1]); } //! Average lbd of lemmas that were distributed to other threads. double avgDistLbd() const { return ratio(sumDistLbd, distributed); } double avgIntJump() const { return ratio(intJumps, intImps); } //! Average length (i.e. number of literals) of guiding paths. double avgGp() const { return ratio(gpLits, gps); } //! Ratio of lemmas integrated. double intRatio() const { return ratio(integrated, distributed); } CLASP_DECLARE_ISTATS(ExtendedStats); CLASP_EXTENDED_STATS(CLASP_STAT_DEFINE,NO_ARG,NO_ARG) }; //! A struct for aggregating statistics maintained in a solver object. struct SolverStats : public CoreStats { SolverStats(); SolverStats(const SolverStats& o); ~SolverStats(); bool enableExtended(); bool enable(const SolverStats& o) { return !o.extra || enableExtended(); } void enableLimit(uint32 size); void reset(); void accu(const SolverStats& o); void accu(const SolverStats& o, bool enableRhs); void swapStats(SolverStats& o); void flush() const; uint32 size() const; const char* key(uint32 i) const; StatisticObject at(const char* key) const; void addTo(const char* key, StatsMap& solving, StatsMap* accu) const; inline void addLearnt(uint32 size, ConstraintType t); inline void addConflict(uint32 dl, uint32 uipLevel, uint32 bLevel, uint32 lbd); inline void addDeleted(uint32 num); inline void addDistributed(uint32 lbd, ConstraintType t); inline void addTest(bool partial); inline void addModel(uint32 decisionLevel); inline void addCpuTime(double t); inline void addSplit(uint32 num = 1); inline void addDomChoice(uint32 num = 1); inline void addIntegratedAsserting(uint32 receivedDL, uint32 jumpDL); inline void addIntegrated(uint32 num = 1); inline void removeIntegrated(uint32 num = 1); inline void addPath(const LitVec::size_type& sz); DynamicLimit* limit; /**< Optional dynamic limit. */ ExtendedStats* extra; /**< Optional extended statistics. */ SolverStats* multi; /**< Not owned: set to accu stats in multishot solving. */ private: SolverStats& operator=(const SolverStats&); }; inline void SolverStats::addLearnt(uint32 size, ConstraintType t) { if (extra) { extra->addLearnt(size, t); } } inline void SolverStats::addDeleted(uint32 num) { if (extra) { extra->deleted += num; } } inline void SolverStats::addDistributed(uint32 lbd, ConstraintType){ if (extra) { ++extra->distributed; extra->sumDistLbd += lbd; } } inline void SolverStats::addIntegrated(uint32 n) { if (extra) { extra->integrated += n;} } inline void SolverStats::removeIntegrated(uint32 n) { if (extra) { extra->integrated -= n;} } inline void SolverStats::addCpuTime(double t) { if (extra) { extra->cpuTime += t; } } inline void SolverStats::addSplit(uint32 num) { if (extra) { extra->splits += num; } } inline void SolverStats::addPath(const LitVec::size_type& sz) { if (extra) { ++extra->gps; extra->gpLits += sz; } } inline void SolverStats::addTest(bool partial) { if (extra) { ++extra->hccTests; extra->hccPartial += (uint32)partial; } } inline void SolverStats::addModel(uint32 DL) { if (extra) { ++extra->models; extra->modelLits += DL; } } inline void SolverStats::addDomChoice(uint32 n) { if (extra) { extra->domChoices += n; } } inline void SolverStats::addIntegratedAsserting(uint32 rDL, uint32 jDL) { if (extra) { ++extra->intImps; extra->intJumps += (rDL - jDL); } } inline void SolverStats::addConflict(uint32 dl, uint32 uipLevel, uint32 bLevel, uint32 lbd) { ++analyzed; if (limit) { limit->update(dl, lbd); } if (extra) { extra->jumps.update(dl, uipLevel, bLevel); } } #undef CLASP_STAT_DEFINE #undef NO_ARG #undef DOXY #undef CLASP_DECLARE_ISTATS /////////////////////////////////////////////////////////////////////////////// // Clauses /////////////////////////////////////////////////////////////////////////////// //! Primitive representation of a clause. struct ClauseRep { typedef ConstraintInfo Info; static ClauseRep create(Literal* cl, uint32 sz, const Info& i = Info()) { return ClauseRep(cl, sz, false, i);} static ClauseRep prepared(Literal* cl, uint32 sz, const Info& i = Info()){ return ClauseRep(cl, sz, true, i); } ClauseRep(Literal* cl = 0, uint32 sz = 0, bool p = false, const Info& i = Info()) : info(i), size(sz), prep(uint32(p)), lits(cl) {} Info info; /*!< Additional clause info. */ uint32 size:31; /*!< Size of array of literals. */ uint32 prep: 1; /*!< Whether lits is already prepared. */ Literal* lits; /*!< Pointer to array of literals (not owned!). */ bool isImp() const { return size > 1 && size < 4; } }; //! (Abstract) base class for clause types. /*! * ClauseHead is used to enforce a common memory-layout for all clauses. * It contains the two watched literals and a cache literal to improve * propagation performance. A virtual call to Constraint::propagate() * is only needed if the other watch is not true and the cache literal * is false. */ class ClauseHead : public Constraint { public: enum { HEAD_LITS = 3, MAX_SHORT_LEN = 5 }; explicit ClauseHead(const InfoType& init); // base interface //! Propagates the head and calls updateWatch() if necessary. PropResult propagate(Solver& s, Literal, uint32& data); //! Type of clause. Type type() const { return info_.type(); } //! Returns the activity of this clause. ScoreType activity() const { return info_.score(); } //! True if this clause currently is the antecedent of an assignment. bool locked(const Solver& s) const; //! Halves the activity of this clause. void decreaseActivity() { info_.score().reduce(); } void resetActivity() { info_.score().reset(); } //! Downcast from LearntConstraint. ClauseHead* clause() { return this; } // clause interface typedef std::pair BoolPair; //! Adds watches for first two literals in head to solver. void attach(Solver& s); void resetScore(ScoreType sc); //! Returns true if head is satisfied w.r.t current assignment in s. bool satisfied(const Solver& s) const; //! Conditional clause? bool tagged() const { return info_.tagged(); } //! Contains aux vars? bool aux() const { return info_.aux(); } bool learnt() const { return info_.learnt(); } uint32 lbd() const { return info_.lbd(); } //! Removes watches from s. virtual void detach(Solver& s); //! Returns the size of this clause. virtual uint32 size() const = 0; //! Returns the literals of this clause in out. virtual void toLits(LitVec& out) const = 0; //! Returns true if this clause is a valid "reverse antecedent" for p. virtual bool isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN) = 0; //! Removes p from clause if possible. /*! * \return * The first component of the returned pair specifies whether or not * p was removed from the clause. * The second component of the returned pair specifies whether * the clause should be kept (false) or removed (true). */ virtual BoolPair strengthen(Solver& s, Literal p, bool allowToShort = true) = 0; protected: struct Local { void init(uint32 sz); bool isSmall() const { return (mem[0] & 1u) == 0u; } bool contracted() const { return (mem[0] & 3u) == 3u; } bool strengthened()const { return (mem[0] & 5u) == 5u; } uint32 size() const { return mem[0] >> 3; } void setSize(uint32 size) { mem[0] = (size << 3) | (mem[0] & 7u); } void markContracted() { mem[0] |= 2u; } void markStrengthened() { mem[0] |= 4u; } void clearContracted() { mem[0] &= ~2u; } void clearIdx() { mem[1] = 0; } uint32 mem[2]; }; bool toImplication(Solver& s); void clearTagged() { info_.setTagged(false); } void setLbd(uint32 x) { info_.setLbd(x); } //! Shall replace the watched literal at position pos with a non-false literal. /*! * \pre pos in [0,1] * \pre s.isFalse(head_[pos]) && s.isFalse(head_[2]) * \pre head_[pos^1] is the other watched literal */ virtual bool updateWatch(Solver& s, uint32 pos) = 0; union { Local local_; SharedLiterals* shared_; }; InfoType info_; Literal head_[HEAD_LITS]; // two watched literals and one cache literal }; //! Allocator for small (at most 32-byte) clauses. class SmallClauseAlloc { public: SmallClauseAlloc(); ~SmallClauseAlloc(); void* allocate() { if(freeList_ == 0) { allocBlock(); } Chunk* r = freeList_; freeList_ = r->next; return r; } void free(void* mem) { Chunk* b = reinterpret_cast(mem); b->next = freeList_; freeList_= b; } private: SmallClauseAlloc(const SmallClauseAlloc&); SmallClauseAlloc& operator=(const SmallClauseAlloc&); struct Chunk { Chunk* next; // enforce ptr alignment unsigned char mem[32 - sizeof(Chunk*)]; }; struct Block { enum { num_chunks = 1023 }; Block* next; unsigned char pad[32-sizeof(Block*)]; Chunk chunk[num_chunks]; }; void allocBlock(); Block* blocks_; Chunk* freeList_; }; /////////////////////////////////////////////////////////////////////////////// // Watches /////////////////////////////////////////////////////////////////////////////// //! Represents a clause watch in a Solver. struct ClauseWatch { //! Clause watch: clause head explicit ClauseWatch(ClauseHead* a_head) : head(a_head) { } ClauseHead* head; struct EqHead { explicit EqHead(ClauseHead* h) : head(h) {} bool operator()(const ClauseWatch& w) const { return head == w.head; } ClauseHead* head; }; }; //! Represents a generic watch in a Solver. struct GenericWatch { //! A constraint and some associated data. explicit GenericWatch(Constraint* a_con, uint32 a_data = 0) : con(a_con), data(a_data) {} //! Calls propagate on the stored constraint and passes the stored data to that constraint. Constraint::PropResult propagate(Solver& s, Literal p) { return con->propagate(s, p, data); } Constraint* con; /**< The constraint watching a certain literal. */ uint32 data; /**< Additional data associated with this watch - passed to constraint on update. */ struct EqConstraint { explicit EqConstraint(Constraint* c) : con(c) {} bool operator()(const GenericWatch& w) const { return con == w.con; } Constraint* con; }; }; //! Watch list type. typedef bk_lib::left_right_sequence WatchList; inline void releaseVec(WatchList& w) { w.clear(true); } /////////////////////////////////////////////////////////////////////////////// // Assignment /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// //! Type for storing reasons for variable assignments together with additional data. /*! * \note On 32-bit systems additional data is stored in the high-word of antecedents. */ struct ReasonStore32 : PodVector::type { uint32 data(uint32 v) const { return decode((*this)[v]);} void setData(uint32 v, uint32 data) { encode((*this)[v], data); } static void encode(Antecedent& a, uint32 data) { a.asUint() = (uint64(data)<<32) | static_cast(a.asUint()); } static uint32 decode(const Antecedent& a) { return static_cast(a.asUint()>>32); } struct value_type { value_type(const Antecedent& a, uint32 d) : ante_(a) { if (d != UINT32_MAX) { encode(ante_, d); assert(data() == d && ante_.type() == Antecedent::Generic); } } const Antecedent& ante() const { return ante_; } uint32 data() const { return ante_.type() == Antecedent::Generic ? decode(ante_) : UINT32_MAX; } Antecedent ante_; }; }; //! Type for storing reasons for variable assignments together with additional data. /* * \note On 64-bit systems additional data is stored in a separate container. */ struct ReasonStore64 : PodVector::type { uint32 dataSize() const { return (uint32)data_.size(); } void dataResize(uint32 nv) { if (nv > dataSize()) data_.resize(nv, UINT32_MAX); } uint32 data(uint32 v) const { return v < dataSize() ? data_[v] : UINT32_MAX; } void setData(uint32 v, uint32 data) { dataResize(v+1); data_[v] = data; } VarVec data_; struct value_type : std::pair { value_type(const Antecedent& a, uint32 d) : std::pair(a, d) {} const Antecedent& ante() const { return first; } uint32 data() const { return second; } }; }; //! A set of configurable values for a variable. /*! * Beside its currently assigned value, a variable * can also have a user, saved, preferred, and default value. * These values are used in sign selection to determine the signed literal * of a variable to be assign first. * During sign selection, the values form a hierarchy: * user > saved > preferred > current sign score of heuristic > default value */ struct ValueSet { ValueSet() : rep(0) {} enum Value { user_value = 0x03u, saved_value = 0x0Cu, pref_value = 0x30u, def_value = 0xC0u }; bool sign() const { return (right_most_bit(rep) & 0xAAu) != 0; } bool empty() const { return rep == 0; } bool has(Value v) const { return (rep & v) != 0; } bool has(uint32 f)const { return (rep & f) != 0; } ValueRep get(Value v) const { return static_cast((rep & v) / right_most_bit(static_cast(v))); } void set(Value which, ValueRep to) { rep &= ~which; rep |= (to * right_most_bit(static_cast(which))); } void save(ValueRep x) { rep &= ~saved_value; rep |= (x << 2); } uint8 rep; }; //! Stores assignment related information. /*! * For each variable v, the class stores * - v's current value (value_free if unassigned) * - the decision level on which v was assign (only valid if value(v) != value_free) * - the reason why v is in the assignment (only valid if value(v) != value_free) * - (optionally) some additional data associated with the reason * . * Furthermore, the class stores the sequences of assignments as a set of * true literals in its trail-member. */ class Assignment { public: typedef PodVector::type AssignVec; typedef PodVector::type PrefVec; typedef bk_lib::detail::if_then_else< sizeof(Constraint*)==sizeof(uint64) , ReasonStore64 , ReasonStore32>::type ReasonVec; typedef ReasonVec::value_type ReasonWithData; Assignment() : front(0), elims_(0), units_(0) { } LitVec trail; // assignment sequence uint32 front; // and "propagation queue" bool qEmpty() const { return front == static_cast(trail.size()); } uint32 qSize() const { return static_cast(trail.size() - front); } Literal qPop() { return trail[front++]; } void qReset() { front = static_cast(trail.size()); } //! Number of variables in the three-valued assignment. uint32 numVars() const { return (uint32)assign_.size(); } //! Number of assigned variables. uint32 assigned() const { return (uint32)trail.size(); } //! Number of free variables. uint32 free() const { return numVars() - (assigned()+elims_); } //! Returns the largest possible decision level. uint32 maxLevel() const { return (1u<<28)-2; } //! Returns v's value in the three-valued assignment. ValueRep value(Var v) const { return ValueRep(assign_[v] & 3u); } //! Returns the decision level on which v was assigned if value(v) != value_free. uint32 level(Var v) const { return assign_[v] >> 4u; } //! Returns true if v was not eliminated from the assignment. bool valid(Var v) const { return (assign_[v] & elim_mask) != elim_mask; } //! Returns the set of preferred values of v. const ValueSet pref(Var v) const { return v < pref_.size() ? pref_[v] : ValueSet(); } //! Returns the reason for v being assigned if value(v) != value_free. const Antecedent& reason(Var v)const { return reason_[v]; } //! Returns the reason data associated with v. uint32 data(Var v) const { return reason_.data(v); } void reserve(uint32 n) { assign_.reserve(n); reason_.reserve(n); } //! Resize to nv variables. void resize(uint32 nv) { assign_.resize(nv); reason_.resize(nv); } //! Adds a var to assignment - initially the new var is unassigned. Var addVar() { assign_.push_back(0); reason_.push_back(0); return numVars()-1; } //! Allocates space for storing preferred values for all variables. void requestPrefs() { if (pref_.size() != assign_.size()) { pref_.resize(assign_.size()); } } //! Eliminates v from the assignment. void eliminate(Var v) { assert(value(v) == value_free && "Can not eliminate assigned var!\n"); if (valid(v)) { assign_[v] = elim_mask|value_true; ++elims_; } } //! Assigns p.var() on level lev to the value that makes p true and stores x as reason for the assignment. /*! * \return true if the assignment is consistent. False, otherwise. * \post If true is returned, p is in trail. Otherwise, ~p is. */ bool assign(Literal p, uint32 lev, const Antecedent& x) { const Var v = p.var(); const ValueRep val = value(v); if (val == value_free) { assert(valid(v)); assign_[v] = (lev<<4) + trueValue(p); reason_[v] = x; trail.push_back(p); return true; } return val == trueValue(p); } bool assign(Literal p, uint32 lev, Constraint* c, uint32 data) { const Var v = p.var(); const ValueRep val = value(v); if (val == value_free) { assert(valid(v)); assign_[v] = (lev<<4) + trueValue(p); reason_[v] = c; reason_.setData(v, data); trail.push_back(p); return true; } return val == trueValue(p); } //! Undos all assignments in the range trail[first, last). /*! * \param first First assignment to be undone. * \param save If true, previous assignment of a var is saved before it is undone. */ void undoTrail(LitVec::size_type first, bool save) { if (!save) { popUntil<&Assignment::clear>(trail[first]); } else { requestPrefs(); popUntil<&Assignment::saveAndClear>(trail[first]); } qReset(); } //! Undos the last assignment. void undoLast() { clear(trail.back().var()); trail.pop_back(); } //! Returns the last assignment as a true literal. Literal last() const { return trail.back(); } Literal&last() { return trail.back(); } /*! * \name Implementation functions * Low-level implementation functions. Use with care and only if you * know what you are doing! */ //@{ uint32 units() const { return units_; } bool seen(Var v, uint8 m) const { return (assign_[v] & (m<<2)) != 0; } void setSeen(Var v, uint8 m) { assign_[v] |= (m<<2); } void clearSeen(Var v) { assign_[v] &= ~uint32(12); } void clearValue(Var v) { assign_[v] &= ~uint32(3); } void setValue(Var v, ValueRep val) { assert(value(v) == val || value(v) == value_free); assign_[v] |= val; } void setReason(Var v, const Antecedent& a) { reason_[v] = a; } void setData(Var v, uint32 data) { reason_.setData(v, data); } void setPref(Var v, ValueSet::Value which, ValueRep to) { pref_[v].set(which, to); } void copyAssignment(Assignment& o) const { o.assign_ = assign_; } bool markUnits() { while (units_ != front) { setSeen(trail[units_++].var(), 3u); } return true; } void setUnits(uint32 ts) { units_ = ts; } void resetPrefs() { pref_.assign(pref_.size(), ValueSet()); } void clear(Var v) { assign_[v] = 0; } void saveAndClear(Var v) { pref_[v].save(value(v)); clear(v); } //@} private: static const uint32 elim_mask = uint32(0xFFFFFFF0u); Assignment(const Assignment&); Assignment& operator=(const Assignment&); template void popUntil(Literal stop) { Literal p; do { p = trail.back(); trail.pop_back(); (this->*op)(p.var()); } while (p != stop); } AssignVec assign_; // for each var: three-valued assignment ReasonVec reason_; // for each var: reason for being assigned (+ optional data) PrefVec pref_; // for each var: set of preferred values uint32 elims_; // number of variables that were eliminated from the assignment uint32 units_; // number of marked top-level assignments }; //! Stores information about a literal that is implied on an earlier level than the current decision level. struct ImpliedLiteral { typedef Assignment::ReasonWithData AnteInfo; ImpliedLiteral(Literal a_lit, uint32 a_level, const Antecedent& a_ante, uint32 a_data = UINT32_MAX) : lit(a_lit) , level(a_level) , ante(a_ante, a_data) { } Literal lit; /**< The implied literal */ uint32 level; /**< The earliest decision level on which lit is implied */ AnteInfo ante; /**< The reason why lit is implied on decision-level level */ }; //! A type for storing ImpliedLiteral objects. struct ImpliedList { typedef PodVector::type VecType; typedef VecType::const_iterator iterator; ImpliedList() : level(0), front(0) {} //! Searches for an entry

in list. Returns 0 if none is found. ImpliedLiteral* find(Literal p) { for (VecType::size_type i = 0, end = lits.size(); i != end; ++i) { if (lits[i].lit == p) { return &lits[i]; } } return 0; } //! Adds a new object to the list. void add(uint32 dl, const ImpliedLiteral& n) { if (dl > level) { level = dl; } lits.push_back(n); } //! Returns true if list contains entries that must be reassigned on current dl. bool active(uint32 dl) const { return dl < level && front != lits.size(); } //! Reassigns all literals that are still implied. bool assign(Solver& s); iterator begin() const { return lits.begin(); } iterator end() const { return lits.end(); } VecType lits; // current set of (out-of-order) implied literals uint32 level; // highest dl on which lits must be reassigned uint32 front; // current starting position in lits }; //@} } #endif clingo-5.2.2/clasp/clasp/statistics.h000066400000000000000000000250741320011352300175400ustar00rootroot00000000000000// // Copyright (c) 2016-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //! \file //! \brief Types and functions for accessing statistics. #ifndef CLASP_STATISTICS_H_INCLUDED #define CLASP_STATISTICS_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include namespace Clasp { template double _getValue(const T* v) { return static_cast(*v); } //! Discriminated union representing either a single statistic value or a composite. class StatisticObject { public: typedef Potassco::Statistics_t Type; struct Hasher { std::size_t operator()(const StatisticObject& o) const { return o.hash(); } }; //! Creates an empty (invalid) object. StatisticObject(); //! Creates a Value object - static_cast(*obj) shall be valid. template static StatisticObject value(const T* obj) { return value(obj); } //! Creates a mapped Value object: f(obj) -> double template static StatisticObject value(const T* obj) { return StatisticObject(obj, registerValue()); } //! Creates a Map object. /*! * The following expression shall be valid: * obj->size(): shall return the number of keys in obj * obj->key(i): shall return the i'th key of this object (i >= 0). * obj->at(const char* k): shall return the StatisticObject under the given key. * If k is invalid, shall either throw an exception or return an empty object. */ template static StatisticObject map(const T* obj) { return StatisticObject(obj, registerMap()); } //! Creates an Array object. /*! * The following expression shall be valid: * obj->size(): shall return the size of the array. * obj->at(i): shall return the StatisticObject under the given key i >= 0. * If k is invalid, shall either throw an exception or return an empty object. */ template static StatisticObject array(const T* obj) { return StatisticObject(obj, registerArray()); } //! Returns the type of this object. Type type() const; //! Returns whether this object is empty. bool empty() const; //! Returns the number of children of this object or 0 if this is not a composite object. uint32 size() const; /*! * \name Map * \pre type() == Map */ //@{ //! Returns the i'th key of this map. /*! * \pre i < size() */ const char* key(uint32 i) const; //! Returns the object under the given key. /*! * \pre k in key([0..size())) */ StatisticObject at(const char* k) const; //@} //! Returns the object at the given index. /*! * \pre Type() == Array * \pre i < size() */ StatisticObject operator[](uint32 i) const; //! Returns the value of this object. /*! * \pre type() == Value */ double value() const; bool operator==(const StatisticObject& rhs) const { return this->handle_ == rhs.handle_; } bool operator<(const StatisticObject& rhs) const { return this->handle_ < rhs.handle_; } std::size_t hash() const; uint64 toRep() const; static StatisticObject fromRep(uint64); private: struct I { typedef const void* ObjPtr; explicit I(Type t) : type(t) {} Type type; }; struct V : I { V(double(*v)(ObjPtr)) : I(Potassco::Statistics_t::Value), value(v) {} double(*value)(ObjPtr); }; struct A : I { A(uint32(*sz)(ObjPtr), StatisticObject(*a)(ObjPtr, uint32)) : I(Potassco::Statistics_t::Array), size(sz), at(a) {} uint32(*size)(ObjPtr); StatisticObject(*at)(ObjPtr, uint32); }; struct M : I { M(uint32(*sz)(ObjPtr), StatisticObject(*a)(ObjPtr, const char*), const char* (*k)(ObjPtr, uint32)) : I(Potassco::Statistics_t::Map), size(sz), at(a), key(k) {} uint32(*size)(ObjPtr); StatisticObject(*at)(ObjPtr, const char*); const char* (*key)(ObjPtr, uint32); }; static uint32 registerType(const I* vtab) { types_.push_back(vtab); return static_cast(types_.size() - 1); } template static uint32 registerValue(); template static uint32 registerMap(); template static uint32 registerArray(); StatisticObject(const void* obj, uint32 type); typedef PodVector::type RegVec; const void* self() const; const I* tid() const; static RegVec types_; uint64 handle_; }; template uint32 StatisticObject::registerArray() { static const struct Array_T : A { Array_T() : A(&Array_T::size, &Array_T::at) {} static uint32 size(ObjPtr obj) { return toU32(static_cast(obj)->size()); } static StatisticObject at(ObjPtr obj, uint32 i) { return static_cast(obj)->at(i); } } vtab_s; static const uint32 id = registerType(&vtab_s); return id; } template uint32 StatisticObject::registerMap() { static const struct Map_T : M { Map_T() : M(&Map_T::size, &Map_T::at, &Map_T::key) {} static inline const T* cast(ObjPtr obj) { return static_cast(obj); } static uint32 size(ObjPtr obj) { return cast(obj)->size(); } static StatisticObject at(ObjPtr obj, const char* k) { return cast(obj)->at(k); } static const char* key(ObjPtr obj, uint32 i) { return cast(obj)->key(i); } } vtab_s; static const uint32 id = registerType(&vtab_s); return id; } template uint32 StatisticObject::registerValue() { static const struct Value_T : V { Value_T() : V(&Value_T::value) {} static double value(ObjPtr obj) { return f(static_cast(obj)); } } vtab_s; static const uint32 id = StatisticObject::registerType(&vtab_s); return id; } //! A type that maps string keys to statistic objects. class StatsMap { public: // StatisticObject uint32 size() const { return sizeVec(keys_); } const char* key(uint32 i) const { return keys_.at(i).first; } StatisticObject at(const char* k) const; // Own interface const StatisticObject* find(const char* k) const; bool add(const char* k, const StatisticObject&); StatisticObject toStats() const { return StatisticObject::map(this); } private: typedef PodVector >::type MapType; MapType keys_; }; //! An array of statistic objects. template class StatsVec : private PodVector::type { public: StatsVec() : own_(true) {} ~StatsVec() { if (own_) { for (iterator it = this->begin(), end = this->end(); it != end; ++it) { delete *it; } } } typedef typename PodVector::type base_type; typedef typename base_type::const_iterator const_iterator; typedef typename base_type::iterator iterator; using base_type::size; using base_type::operator[]; using base_type::begin; using base_type::end; void growTo(uint32 newSize) { if (newSize > size()) this->resize(newSize); } void reset() { for (iterator it = this->begin(), end = this->end(); it != end; ++it) { (*it)->reset(); } } StatisticObject at(uint32 i) const { return get_(this->base_type::at(i), bk_lib::detail::int2type()); } StatisticObject toStats() const { return StatisticObject::array(this); } void acquire() { own_ = true; } void release() { own_ = false; } private: static StatisticObject get_(const T* ptr, bk_lib::detail::int2type) { return StatisticObject::map(ptr); } static StatisticObject get_(const T* ptr, bk_lib::detail::int2type) { return StatisticObject::array(ptr); } static StatisticObject get_(const T* ptr, bk_lib::detail::int2type) { return StatisticObject::value(ptr); } StatsVec(const StatsVec&); StatsVec& operator=(const StatsVec&); bool own_; }; //! A class for traversing and querying statistics. /*! * \ingroup clingo */ class ClaspStatistics : public Potassco::AbstractStatistics { public: typedef Potassco::Statistics_t Type; ClaspStatistics(); ~ClaspStatistics(); // Base interface virtual Key_t root() const; virtual Type type(Key_t key) const; virtual size_t size(Key_t key) const; virtual Key_t at(Key_t arrK, size_t index) const; virtual const char* key(Key_t mapK, size_t i) const; virtual Key_t get(Key_t mapK, const char* key) const; virtual double value(Key_t key) const; // Register interface Key_t setRoot(const StatisticObject&); bool removeStat(const StatisticObject&, bool recurse); bool removeStat(Key_t k, bool recurse); void update(); StatisticObject findObject(Key_t root, const char* path, Key_t* track = 0) const; StatisticObject getObject(Key_t k) const; private: ClaspStatistics(const ClaspStatistics&); ClaspStatistics& operator=(const ClaspStatistics&); Key_t root_; struct Impl; Impl* impl_; }; struct SolverStats; struct JumpStats; struct ExtendedStats; struct ProblemStats; //! Interface for visiting statistics. /*! * \ingroup facade */ class StatsVisitor { public: enum Operation { Enter, Leave } ; virtual ~StatsVisitor(); // compound virtual bool visitGenerator(Operation op); // default: return true virtual bool visitThreads(Operation op); // default: return true virtual bool visitTester(Operation op); // default: return true virtual bool visitHccs(Operation op); // default: return true // leafs virtual void visitThread(uint32, const SolverStats& stats); virtual void visitHcc(uint32, const ProblemStats& p, const SolverStats& s); virtual void visitLogicProgramStats(const Asp::LpStats& stats) = 0; virtual void visitProblemStats(const ProblemStats& stats) = 0; virtual void visitSolverStats(const SolverStats& stats) = 0; }; } #endif clingo-5.2.2/clasp/clasp/unfounded_check.h000066400000000000000000000305371320011352300204720ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_UNFOUNDED_CHECK_H_INCLUDED #define CLASP_UNFOUNDED_CHECK_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include #include #include #include namespace Clasp { class LoopFormula; //! Clasp's default unfounded set checker. /*! * \ingroup propagator * Searches for unfounded atoms by checking the positive dependency graph (PDG) * * Basic Idea: * - For each (non-false) atom a, let source(a) be a body B in body(a) that provides an external support for a * - If no such B exists, a must be false * - If source(a) becomes false and a is not false: * - Let Q = {}; * - add a to Q * - For each B' s.th B' is not external to Q * - add { a' | source(a') = B } to Q * - Try to find new sources for all atoms a in Q */ class DefaultUnfoundedCheck : public PostPropagator { public: typedef Asp::PrgDepGraph DependencyGraph; typedef DependencyGraph::NodeId NodeId; typedef DependencyGraph::BodyNode BodyNode; typedef DependencyGraph::AtomNode AtomNode; typedef const DependencyGraph* ConstGraphPtr; typedef DependencyGraph* GraphPtr; //! Defines the supported reasons for explaining assignments. enum ReasonStrategy { common_reason = LoopReason_t::Explicit, /*!< one reason for each unfounded set but one clause for each atom */ only_reason = LoopReason_t::Implicit, /*!< store only the reason but don't learn a nogood */ distinct_reason, /*!< distinct reason and clause for each unfounded atom */ shared_reason, /*!< one shared loop formula for each unfounded set */ no_reason, /*!< do no compute reasons for unfounded sets (only valid if learning is disabled!) */ }; explicit DefaultUnfoundedCheck(DependencyGraph& graph, ReasonStrategy st = common_reason); ~DefaultUnfoundedCheck(); ReasonStrategy reasonStrategy() const { return strategy_; } void setReasonStrategy(ReasonStrategy rs); ConstGraphPtr graph() const { return graph_; } uint32 nodes() const { return static_cast(atoms_.size() + bodies_.size()); } // base interface uint32 priority() const { return uint32(priority_reserved_ufs); } bool init(Solver&); void reset(); bool propagateFixpoint(Solver& s, PostPropagator* ctx); bool isModel(Solver& s); bool valid(Solver& s); bool simplify(Solver& s, bool); void destroy(Solver* s, bool detach); private: DefaultUnfoundedCheck(const DefaultUnfoundedCheck&); DefaultUnfoundedCheck& operator=(const DefaultUnfoundedCheck&); enum UfsType { ufs_none, ufs_poly, ufs_non_poly }; enum WatchType { watch_source_false = 0, watch_head_false = 1, watch_head_true = 2, watch_subgoal_false= 3, }; // data for each body struct BodyData { BodyData() : watches(0), picked(0) {} uint32 watches : 31; // how many atoms watch this body as source? uint32 picked : 1; // flag used in computeReason() uint32 lower_or_ext; // unsourced preds or index of extended body }; struct BodyPtr { BodyPtr(const BodyNode* n, uint32 i) : node(n), id(i) {} const BodyNode* node; uint32 id; }; // data for extended bodies struct ExtData { ExtData(weight_t bound, uint32 preds) : lower(bound), slack(-bound) { for (uint32 i = 0; i != flagSize(preds); ++i) { flags[i] = 0; } } bool addToWs(uint32 idx, weight_t w) { const uint32 fIdx = (idx / 32); const uint32 m = (1u << (idx & 31)); assert((flags[fIdx] & m) == 0); flags[fIdx] |= m; return (lower -= w) <= 0; } bool inWs(uint32 idx) const { const uint32 fIdx = (idx / 32); const uint32 m = (1u << (idx & 31)); return (flags[fIdx] & m) != 0; } void removeFromWs(uint32 idx, weight_t w) { if (inWs(idx)) { lower += w; flags[(idx / 32)] &= ~(uint32(1) << (idx & 31)); } } static uint32 flagSize(uint32 preds) { return (preds+31)/32; } weight_t lower; weight_t slack; POTASSCO_WARNING_BEGIN_RELAXED uint32 flags[0]; POTASSCO_WARNING_END_RELAXED }; // data for each atom struct AtomData { AtomData() : source(nill_source), todo(0), ufs(0), validS(0) {} // returns the body that is currently watched as possible source NodeId watch() const { return source; } // returns true if atom has currently a source, i.e. a body that can still define it bool hasSource() const { return validS; } // mark source as invalid but keep the watch void markSourceInvalid() { validS = 0; } // restore validity of source void resurrectSource() { validS = 1; } // sets b as source for this atom void setSource(NodeId b) { source = b; validS = 1; } static const uint32 nill_source = (uint32(1) << 29)-1; uint32 source : 29; // id of body currently watched as source uint32 todo : 1; // in todo-queue? uint32 ufs : 1; // in ufs-queue? uint32 validS : 1; // is source valid? }; // Watch-structure used to update extended bodies affected by literal assignments struct ExtWatch { NodeId bodyId; uint32 data; }; // Minimality checker for disjunctive logic programs. struct MinimalityCheck { typedef SolveParams::FwdCheck FwdCheck; explicit MinimalityCheck(const FwdCheck& fwd); bool partialCheck(uint32 level); void schedNext(uint32 level, bool ok); FwdCheck fwd; uint32 high; uint32 low; uint32 next; uint32 scc; }; // ------------------------------------------------------------------------------------------- // constraint interface PropResult propagate(Solver&, Literal, uint32& data) { uint32 index = data >> 2; uint32 type = (data & 3u); if (type != watch_source_false || bodies_[index].watches) { invalidQ_.push_back(data); } return PropResult(true, true); } void reason(Solver& s, Literal, LitVec&); // ------------------------------------------------------------------------------------------- // initialization BodyPtr getBody(NodeId bId) const { return BodyPtr(&graph_->getBody(bId), bId); } void initBody(const BodyPtr& n); void initExtBody(const BodyPtr& n); void initSuccessors(const BodyPtr& n, weight_t lower); void addWatch(Literal, uint32 data, WatchType type); void addExtWatch(Literal p, const BodyPtr& n, uint32 data); struct InitExtWatches { void operator()(Literal p, uint32 idx, bool ext) const { extra->slack += B->node->pred_weight(idx, ext); self->addExtWatch(~p, *B, (idx<<1)+uint32(ext)); if (ext && !self->solver_->isFalse(p)) { extra->addToWs(idx, B->node->pred_weight(idx, true)); } } DefaultUnfoundedCheck* self; const BodyPtr* B; ExtData* extra; }; struct RemExtWatches { void operator()(Literal p, uint32, bool) const { s->removeWatch(~p, self); } Constraint* self; Solver* s; }; // ------------------------------------------------------------------------------------------- // propagating source pointers void propagateSource(); struct AddSource { // an atom in a body has a new source, check if body is now a valid source explicit AddSource(DefaultUnfoundedCheck* u) : self(u) {} // normal body void operator()(NodeId bId) const { BodyPtr n(self->getBody(bId)); if (--self->bodies_[bId].lower_or_ext == 0 && !self->solver_->isFalse(n.node->lit)) { self->forwardSource(n); } } // extended body void operator()(NodeId bId, uint32 idx) const; DefaultUnfoundedCheck* self; }; struct RemoveSource {// an atom in a body has lost its source, check if body is no longer a valid source explicit RemoveSource(DefaultUnfoundedCheck* u, bool add = false) : self(u), addTodo(add) {} // normal body void operator()(NodeId bId) const { if (++self->bodies_[bId].lower_or_ext == 1 && self->bodies_[bId].watches != 0) { self->forwardUnsource(self->getBody(bId), addTodo); } } // extended body void operator()(NodeId bId, uint32 idx) const; DefaultUnfoundedCheck* self; bool addTodo; }; void setSource(NodeId atom, const BodyPtr& b); void removeSource(NodeId bodyId); void forwardSource(const BodyPtr& n); void forwardUnsource(const BodyPtr& n, bool add); void updateSource(AtomData& atom, const BodyPtr& n); // ------------------------------------------------------------------------------------------- // finding & propagating unfounded sets void updateAssignment(Solver& s); bool findSource(NodeId atom); bool isValidSource(const BodyPtr&); void addUnsourced(const BodyPtr&); bool falsifyUfs(UfsType t); bool assertAtom(Literal a, UfsType t); void computeReason(UfsType t); void addIfReason(const BodyPtr&, uint32 uScc); bool isExternal(const BodyPtr&, weight_t& slack) const; void addDeltaReason(const BodyPtr& body, uint32 uScc); void addReasonLit(Literal); void createLoopFormula(); struct AddReasonLit { void operator()(Literal p, NodeId id, bool ext) const { if (self->solver_->isFalse(p) && slack >= 0) { slack -= node->pred_weight(id, ext); self->addReasonLit(p); } } DefaultUnfoundedCheck* self; const BodyNode* node; mutable weight_t slack; }; UfsType findUfs(Solver& s, bool checkNonHcf); UfsType findNonHcfUfs(Solver& s); // ------------------------------------------------------------------------------------------- bool pushTodo(NodeId at) { return (atoms_[at].todo == 0 && (todo_.push(at), atoms_[at].todo = 1) != 0); } bool pushUfs(NodeId at) { return (atoms_[at].ufs == 0 && (ufs_.push(at), atoms_[at].ufs = 1) != 0); } void resetTodo() { while (!todo_.empty()){ atoms_[todo_.pop_ret()].todo = 0; } todo_.clear(); } void resetUfs() { while (!ufs_.empty()) { atoms_[ufs_.pop_ret()].ufs = 0; } ufs_.clear(); } // ------------------------------------------------------------------------------------------- typedef PodVector::type AtomVec; typedef PodVector::type BodyVec; typedef PodVector::type ExtVec; typedef PodVector::type WatchVec; typedef PodQueue IdQueue; typedef SingleOwnerPtr MiniPtr; // ------------------------------------------------------------------------------------------- Solver* solver_; // my solver GraphPtr graph_; // PBADG MiniPtr mini_; // minimality checker (only for DLPs) AtomVec atoms_; // data for each atom BodyVec bodies_; // data for each body IdQueue todo_; // ids of atoms that recently lost their source IdQueue ufs_; // ids of atoms that are unfounded wrt the current assignment (limited to one scc) VarVec invalidQ_; // ids of invalid elements to be processed VarVec sourceQ_; // source-pointer propagation queue ExtVec extended_; // data for each extended body WatchVec watches_; // watches for handling choice-, cardinality- and weight rules VarVec pickedExt_; // extended bodies visited during reason computation LitVec loopAtoms_; // only used if strategy_ == shared_reason LitVec activeClause_;// activeClause_[0] is the current unfounded atom LitVec* reasons_; // only used if strategy_ == only_reason. reasons_[v] reason why v is unfounded ConstraintInfo info_; // info on active clause ReasonStrategy strategy_; // what kind of reasons to compute? }; } #endif clingo-5.2.2/clasp/clasp/util/000077500000000000000000000000001320011352300161425ustar00rootroot00000000000000clingo-5.2.2/clasp/clasp/util/hash.h000066400000000000000000000034201320011352300172350ustar00rootroot00000000000000// // Copyright (c) 2016-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_HASH_H_INCLUDED #define CLASP_HASH_H_INCLUDED #include #include namespace Clasp { //! Hasher for strings. /*! * \see http://research.microsoft.com/en-us/people/palarson/ */ struct StrHash { std::size_t operator()(const char* str) const { std::size_t h = 0; for (const char* s = str; *s; ++s) { h = h * 101 + static_cast(*s); } return h; } }; //! Comparison function for C-strings to be used with hash map/set. struct StrEq { bool operator()(const char* lhs, const char* rhs) const { return std::strcmp(lhs, rhs) == 0; } }; } #endif clingo-5.2.2/clasp/clasp/util/indexed_priority_queue.h000066400000000000000000000131031320011352300230760ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef BK_LIB_INDEXED_PRIORITY_QUEUE_H_INCLUDED #define BK_LIB_INDEXED_PRIORITY_QUEUE_H_INCLUDED #ifdef _MSC_VER #pragma warning (disable : 4267) #pragma warning (disable : 4244) #pragma once #endif #include #include "pod_vector.h" namespace bk_lib { namespace detail { typedef std::size_t key_type; const key_type noKey = static_cast(-1); inline key_type heap_root() { return 0; } inline key_type heap_left(std::size_t i) { return (i<<1)+1; } inline key_type heap_right(std::size_t i) { return (i+1)<<1; } inline key_type heap_parent(std::size_t i) { return (i-1)>>1; } } // Note: Uses a Max-Heap! template < class Cmp // sort-predicate - if Cmp(k1, k2) == true, n1 has higher priority than n2 > class indexed_priority_queue { public: typedef detail::key_type key_type; typedef pod_vector index_container_type; typedef std::size_t size_type; typedef Cmp compare_type; explicit indexed_priority_queue( const compare_type& c = compare_type() ); indexed_priority_queue(const indexed_priority_queue& other); indexed_priority_queue& operator=(const indexed_priority_queue& other) { indices_ = other.indices_; heap_ = other.heap_; compare_ = other.compare_; return *this; } const compare_type& key_compare() const { return compare_; } bool empty() const { return heap_.empty(); } void reserve(size_type n) { indices_.reserve(n); } void push(key_type k) { assert( !is_in_queue(k) ); if ((key_type)indices_.size() <= k) { if (indices_.capacity() <= k) { indices_.reserve(((k+1)*3)>>1); } indices_.resize(k+1, detail::noKey); } indices_[k] = (key_type)heap_.size(); heap_.push_back(k); siftup(indices_[k]); } void pop() { assert(!empty()); key_type x = heap_[0]; heap_[0] = heap_.back(); indices_[heap_[0]] = 0; indices_[x] = detail::noKey; heap_.pop_back(); if (heap_.size() > 1) {siftdown(0);} } void clear() { heap_.clear(); indices_.clear(); } template void swapMem(indexed_priority_queue& o) { clear(); o.clear(); heap_.swap(o.heap_); indices_.swap(o.indices_); } size_type size( ) const { return heap_.size(); } key_type top() const { assert(!empty()); return heap_[0]; } void update(key_type k) { if (!is_in_queue(k)) { push(k); } else { siftup(indices_[k]); siftdown(indices_[k]); } } // call if priority of k has increased void increase(key_type k) { assert(is_in_queue(k)); siftup(indices_[k]); } // call if priority of k has decreased void decrease(key_type k) { assert(is_in_queue(k)); siftdown(indices_[k]); } bool is_in_queue(key_type k) const { assert(valid_key(k)); return k < (key_type)indices_.size() && indices_[k] != detail::noKey; } void remove(key_type k) { if (is_in_queue(k)) { key_type kInHeap = indices_[k]; heap_[kInHeap] = heap_.back(); indices_[heap_.back()] = kInHeap; heap_.pop_back(); indices_[k] = detail::noKey; if (heap_.size() > 1 && kInHeap != (key_type)heap_.size()) { siftup(kInHeap); siftdown(kInHeap); } } } private: template friend class indexed_priority_queue; bool valid_key(key_type k) const { return k != detail::noKey; } index_container_type indices_; index_container_type heap_; compare_type compare_; void siftup(key_type n) { using namespace detail; key_type x = heap_[n]; key_type p = heap_parent(n); while (n != 0 && compare_(x, heap_[p])){ heap_[n] = heap_[p]; indices_[heap_[n]] = n; n = p; p = heap_parent(n); } heap_[n] = x; indices_[x] = n; } void siftdown(key_type n) { using namespace detail; key_type x = heap_[n]; while (heap_left(n) < (key_type)heap_.size()){ key_type child = smaller_child(n); if (!compare_(heap_[child], x)) { break; } heap_[n] = heap_[child]; indices_[heap_[n]] = n; n = child; } heap_[n] = x; indices_[x] = n; } key_type smaller_child(size_type n) const { using namespace detail; return heap_right(n) < (key_type)heap_.size() && compare_(heap_[heap_right(n)], heap_[heap_left(n)]) ? heap_right(n) : heap_left(n); } }; template indexed_priority_queue::indexed_priority_queue( const compare_type& c ) : indices_() , heap_() , compare_(c) { } template indexed_priority_queue::indexed_priority_queue(const indexed_priority_queue& other) : indices_(other.indices_) , heap_(other.heap_) , compare_(other.compare_) { } } #endif clingo-5.2.2/clasp/clasp/util/left_right_sequence.h000066400000000000000000000305151320011352300223360ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef BK_LIB_LEFT_RIGHT_SEQUENCE_INCLUDED #define BK_LIB_LEFT_RIGHT_SEQUENCE_INCLUDED #ifdef _MSC_VER #pragma warning( push ) #pragma warning (disable : 4200) #endif #include "type_manip.h" #include #include #include namespace bk_lib { namespace detail { // base class for left_right_sequence // see below template class left_right_rep { public: typedef L left_type; typedef R right_type; typedef unsigned int size_type; typedef L* left_iterator; typedef const L* const_left_iterator; typedef std::reverse_iterator right_iterator; typedef std::reverse_iterator const_right_iterator; typedef typename bk_lib::detail::align_of::type left_align_type; typedef typename bk_lib::detail::align_of::type right_align_type; ///@cond typedef typename bk_lib::detail::if_then_else< sizeof(left_type) >= sizeof(right_type), left_type, right_type>::type max_type; typedef typename bk_lib::detail::if_then_else< sizeof(left_align_type) >= sizeof(right_align_type), left_align_type, right_align_type>::type align_type; ///@endcond left_right_rep() : buf_(0), cap_(0), free_(0), left_(0), right_(0) {} bool empty() const { return left_ == 0 && right_ == cap_; } size_type left_size() const { return left_/sizeof(left_type); } size_type right_size() const { return (cap_-right_)/sizeof(right_type); } size_type size() const { return left_size() + right_size(); } size_type left_capacity() const { return (cap_ / sizeof(left_type)); } size_type right_capacity()const { return (cap_ / sizeof(right_type)); } const_left_iterator left_begin() const { return const_left_iterator(reinterpret_cast(begin())); } const_left_iterator left_end() const { return const_left_iterator(reinterpret_cast(buf_+left_)); } left_iterator left_begin() { return left_iterator(reinterpret_cast(begin())); } left_iterator left_end() { return left_iterator(reinterpret_cast(buf_+left_)); } const_right_iterator right_begin()const { return const_right_iterator(reinterpret_cast(end())); } const_right_iterator right_end() const { return const_right_iterator(reinterpret_cast(buf_+right_)); } right_iterator right_begin() { return right_iterator(reinterpret_cast(end())); } right_iterator right_end() { return right_iterator(reinterpret_cast(buf_+right_)); } const left_type& left(size_type i)const { return *(left_begin()+i); } left_type& left(size_type i) { return *(left_begin()+i); } void clear(bool releaseMem = false) { if (releaseMem) { release(); buf_ = 0; cap_ = 0; free_ = 0; } left_ = 0; right_= cap_; } void push_left(const left_type& x) { if ((left_ + sizeof(left_type)) > right_) { realloc(); } new (left())left_type(x); left_ += sizeof(left_type); } void push_right(const right_type& x) { if ( (left_ + sizeof(right_type)) > right_ ) { realloc(); } right_ -= sizeof(right_type); new (right()) right_type(x); } void pop_left() { assert(left_size() != 0); left_ -= sizeof(left_type); } void pop_right() { assert(right_size() != 0); right_ += sizeof(right_type); } void erase_left(left_iterator it) { if (it != left_end()) { left_iterator x = it++; std::memmove(x, it, (left_end()-it)*sizeof(left_type)); left_ -= sizeof(left_type); } } void erase_left_unordered(left_iterator it) { if (it != left_end()) { left_ -= sizeof(left_type); *it = *reinterpret_cast(left()); } } void erase_right(right_iterator it) { if (it != right_end()) { right_type* r = (++it).base(); right_type* b = reinterpret_cast(right()); assert(r >= b); std::memmove(b+1, b, (r-b)*sizeof(right_type)); right_ += sizeof(right_type); } } void erase_right_unordered(right_iterator it) { if (it != right_end()) { *it = *reinterpret_cast(right()); right_+= sizeof(right_type); } } void shrink_left(left_iterator it) { left_ = static_cast((it - left_begin())*sizeof(left_type)); } void shrink_right(right_iterator it) { buf_type* x = reinterpret_cast(it.base()); right_ = static_cast(x - begin()); } enum { block_size = ((sizeof(max_type)+(sizeof(align_type)-1)) / sizeof(align_type)) * sizeof(align_type) }; protected: left_right_rep(const left_right_rep&) { } left_right_rep& operator=(const left_right_rep&) { return *this; } typedef unsigned char buf_type; buf_type* begin() { return buf_; } const buf_type* begin()const { return buf_; } buf_type* end() { return buf_+cap_; } const buf_type* end() const { return buf_+cap_; } buf_type* left() { return buf_+left_; } buf_type* right() { return buf_+right_; } size_type capacity()const { return cap_ / block_size; } size_type raw_size()const { return left_ + (cap_-right_); } void release() { if (free_ != 0) { ::operator delete(buf_); } } void realloc(); buf_type* buf_; size_type cap_ : 31; size_type free_: 1; size_type left_; size_type right_; }; template void left_right_rep::realloc() { size_type new_cap = ((capacity()*3)>>1) * block_size; size_type min_cap = 4 * block_size; if (new_cap < min_cap) new_cap = min_cap; buf_type* temp = (buf_type*)::operator new(new_cap*sizeof(buf_type)); // copy left std::memcpy(temp, begin(), left_size()*sizeof(L)); // copy right size_type r = cap_ - right_; std::memcpy(temp+(new_cap-r), right(), right_size() * sizeof(R)); // swap release(); buf_ = temp; cap_ = new_cap; free_ = 1; right_ = new_cap - r; } // always store sequence in heap-allocated buffer template struct no_inline_buffer : public left_right_rep { typedef typename left_right_rep::buf_type buf_type; enum { inline_raw_cap = 0 }; buf_type* extra() { return 0; } }; // store small sequences directly inside of object template struct with_inline_buffer : public left_right_rep { typedef typename left_right_rep::buf_type buf_type; typedef typename left_right_rep::align_type align_type; enum { inline_raw_cap = cap }; buf_type* extra() { return rep_.mem; } union X { align_type align; buf_type mem[inline_raw_cap]; } rep_; }; // select proper base class for left_right_sequence based // on parameter i template struct select_base { private: typedef unsigned char buf_type; typedef left_right_rep base_type; typedef typename base_type::size_type size_type; typedef typename base_type::align_type align_type; typedef no_inline_buffer no_extra_type; typedef with_inline_buffer with_extra_type; enum { padding = sizeof(with_extra_type) - (sizeof(no_extra_type)+sizeof(align_type)) }; enum { size_with_pad = sizeof(no_extra_type) + padding }; enum { store_extra = (i > size_with_pad) && (i - size_with_pad) >= base_type::block_size }; enum { inline_raw_cap = store_extra ? ((i - size_with_pad)/base_type::block_size)*base_type::block_size : 0 }; public: typedef typename if_then_else< store_extra!=0, with_inline_buffer, no_inline_buffer >::type type; }; } // bk_lib::detail //! Stores two sequences in one contiguous memory block /*! * The left sequence grows from left to right, while the * right sequence grows from right to left. On overlap, the * memory block is automatically extended. * * \param L value type of left sequence * \param R value type of right sequence * \param i max size on stack * \pre L and R can be copied with memcpy (i.e. have trivial copy constructor and trivial destructor) */ template class left_right_sequence : public bk_lib::detail::select_base::type { public: typedef typename bk_lib::detail::select_base::type base_type; typedef typename base_type::left_type left_type; typedef typename base_type::right_type right_type; typedef typename base_type::size_type size_type; typedef typename base_type::align_type align_type; typedef typename base_type::max_type max_type; typedef typename base_type::buf_type buf_type; typedef typename base_type::left_iterator left_iterator; typedef typename base_type::const_left_iterator const_left_iterator; typedef typename base_type::right_iterator right_iterator; typedef typename base_type::const_right_iterator const_right_iterator; left_right_sequence() { this->buf_ = this->extra(); this->cap_ = base_type::inline_raw_cap; this->free_ = 0; this->left_ = 0; this->right_= base_type::inline_raw_cap; } left_right_sequence(const left_right_sequence& other); ~left_right_sequence() { this->release(); } left_right_sequence& operator=(const left_right_sequence&); void try_shrink() { if (this->raw_size() <= base_type::inline_raw_cap && this->buf_ != this->extra()) { buf_type* e = this->extra(); size_type c = base_type::inline_raw_cap; size_type r = c - (this->right_size()*sizeof(right_type)); std::memcpy(e, this->begin(), this->left_size() * sizeof(left_type)); std::memcpy(e+r, this->right(), this->right_size()* sizeof(right_type)); this->release(); this->buf_ = e; this->cap_ = c; this->free_ = 0; this->right_= r; } } void move(left_right_sequence& other) { this->clear(true); if (other.raw_size() <= base_type::inline_raw_cap) { copy(other); other.clear(true); } else { this->buf_ = other.buf_; this->cap_ = other.cap_; this->free_ = other.free_; this->left_ = other.left_; this->right_ = other.right_; other.buf_ = other.extra(); other.cap_ = base_type::inline_raw_cap; other.free_ = 0; other.left_ = 0; other.right_= base_type::inline_raw_cap; } } private: void copy(const left_right_sequence&); }; template void left_right_sequence::copy(const left_right_sequence& other) { size_type os = other.raw_size(); if ( os <= base_type::inline_raw_cap ) { this->buf_ = this->extra(); this->cap_ = base_type::inline_raw_cap; this->free_= 0; } else { os = ((os + (base_type::block_size-1)) / base_type::block_size) * base_type::block_size; this->buf_ = (buf_type*)::operator new(os*sizeof(buf_type)); this->cap_ = os; this->free_= 1; } this->left_ = other.left_; this->right_= this->cap_ - (other.right_size()*sizeof(right_type)); std::memcpy(this->begin(), other.begin(), other.left_size()*sizeof(left_type)); std::memcpy(this->right(), const_cast(other).right(), other.right_size()*sizeof(right_type)); } template left_right_sequence::left_right_sequence(const left_right_sequence& other) : base_type(other) { copy(other); } template left_right_sequence& left_right_sequence::operator=(const left_right_sequence& other) { if (this != &other) { this->release(); copy(other); } return *this; } } // namespace bk_lib #ifdef _MSC_VER #pragma warning(pop) #endif #endif clingo-5.2.2/clasp/clasp/util/misc_types.h000066400000000000000000000367731320011352300205120ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_UTIL_MISC_TYPES_H_INCLUDED #define CLASP_UTIL_MISC_TYPES_H_INCLUDED #include #include // std::pair #include // std::unary_function, std::binary_function #include #include /*! * \file * \brief Some utility types and functions. */ namespace Clasp { /*! * \defgroup misc Miscellaneous * \brief Miscellaneous and Internal Stuff not specific to clasp. */ //@{ template inline T bit_mask(unsigned n) { return static_cast(1) << n; } //! Returns whether bit n is set in x. template inline bool test_bit(T x, unsigned n) { return (x & bit_mask(n)) != 0; } template inline T clear_bit(T x, unsigned n) { return x & ~bit_mask(n); } template inline T set_bit(T x, unsigned n) { return x | bit_mask(n); } template inline T toggle_bit(T x, unsigned n) { return x ^ bit_mask(n); } template inline T& store_clear_bit(T& x, unsigned n) { return (x &= ~bit_mask(n)); } template inline T& store_set_bit(T& x, unsigned n) { return (x |= bit_mask(n)); } template inline T& store_toggle_bit(T& x, unsigned n) { return (x ^= bit_mask(n)); } template inline T right_most_bit(T x) { return x & (-x); } inline uint32 log2(uint32 x) { uint32 ln = 0; if (x & 0xFFFF0000u) { x >>= 16; ln |= 16; } if (x & 0xFF00u ) { x >>= 8; ln |= 8; } if (x & 0xF0u ) { x >>= 4; ln |= 4; } if (x & 0xCu ) { x >>= 2; ln |= 2; } if (x & 0x2u ) {/*x>>=1*/; ln |= 1; } return ln; } //! Computes n choose k. inline uint64 choose(unsigned n, unsigned k) { if (k == 0) return 1; if (k > n) return 0; if (2 * k > n) { return choose(n, n-k);} uint64 res = n; for (unsigned i = 2 ; i <= k; ++i) { res *= (n + 1 - i); res /= i; } return res; } inline double ratio(uint64 x, uint64 y) { return y ? static_cast(x) / static_cast(y) : 0; } inline double percent(uint64 x, uint64 y) { return ratio(x, y) * 100.0; } //! A very simple but fast Pseudo-random number generator. /*! * \note This class is a replacement for the standard rand-function. It is provided * in order to get reproducible random numbers among different compilers. */ class RNG { public: explicit RNG(uint32 seed = 1) : seed_(seed) {} //! Sets the starting point for random-number generation. /*! * The function sets the starting point for generating a series of pseudorandom integers. * To reinitialize the generator, use 1 as the seed argument. Any other value for seed * sets the generator to a random starting point. Calling rand() before any call to srand() * generates the same sequence as calling srand() with seed passed as 1. */ void srand(uint32 seed) { seed_ = seed; } //! Generates a pseudorandom number /*! * The rand function returns a pseudorandom integer in the range 0 to 32767 * Use the srand function to seed the pseudorandom-number generator before calling rand. */ uint32 rand() { return( ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff ); } //! random floating point number in the range [0, 1.0) double drand() { return this->rand()/static_cast(0x8000u); } //! random number in the range [0, max) unsigned irand(unsigned max) { return static_cast(drand() * max); } uint32 seed() const { return seed_; } uint32 operator()(unsigned max) { return irand(max); } uint32 operator()() { return rand(); } private: uint32 seed_; }; //! Updates the given exponential moving average with the given sample. /*! * Computes ema = currentEma + ((double(sample) - currentEma)*alpha); */ template inline double exponentialMovingAverage(double currentEma, T sample, double alpha) { return (static_cast(sample) * alpha) + (currentEma * (1.0 - alpha)); } //! Updates the given moving average with the given sample. template inline double cumulativeMovingAverage(double currentAvg, T sample, uint64 numSeen) { return (static_cast(sample) + (currentAvg * numSeen)) / static_cast(numSeen + 1); } //! An unary operator function that calls p->destroy(). struct DestroyObject { template void operator()(T* p) const { if (p) p->destroy(); } }; //! An unary operator function that calls delete p. struct DeleteObject { template void operator()(T* p) const { delete p; } }; //! An unary operator function that calls p->release(). struct ReleaseObject { template void operator()(T* p) const { if (p) p->release(); } }; //! An unary operator function that returns whether its argument is 0. struct IsNull { template bool operator()(const T& p) const { return p == 0; } }; //! A predicate that checks whether a std::pair contains a certain value. template struct PairContains { PairContains(const T& p) : p_(p) {} bool operator()(const std::pair& s) const { return s.first == p_ || s.second == p_; } T p_; }; //! Removes from the container c the first occurrence of a value v for which p(v) returns true. /*! * \pre C is a container that provides back() and pop_back() * \note Removal is implemented by replacing the element to be removed with * the back()-element followed by a call to pop_back(). */ template void remove_first_if(C& cont, const P& p) { for (typename C::iterator it = cont.begin(), end = cont.end(); it != end; ++it) { if (p(*it)) { *it = cont.back(); cont.pop_back(); return; } } } //! An unary operator function that simply returns its argument. template struct identity : std::unary_function{ T& operator()(T& x) const { return x; } const T& operator()(const T& x) const { return x; } }; //! An unary operator function that returns the first value of a std::pair. template struct select1st : std::unary_function { typename P::first_type& operator()(P& x) const { return x.first; } const typename P::first_type& operator()(const P& x) const { return x.first; } }; //! An unary operator function that returns the second value of a std::pair. template struct select2nd : std::unary_function { typename P::second_type& operator()(P& x) const { return x.second; } const typename P::second_type& operator()(const P& x) const { return x.second; } }; //! An unary operator function that returns Op1(Op2(x)). template struct compose_1 : public std::unary_function< typename OP2::argument_type, typename OP1::result_type> { compose_1(const OP1& op1, const OP2& op2) : op1_(op1) , op2_(op2) {} typename OP1::result_type operator()(const typename OP2::argument_type& x) const { return op1_(op2_(x)); } protected: OP1 op1_; OP2 op2_; }; /*! * A template helper function used to construct objects of type compose_1, * where the component types are based on the data types passed as parameters. */ template inline compose_1 compose1(const OP1& op1, const OP2& op2) { return compose_1(op1, op2); } //! An unary operator function that returns OP1(OP2(x), OP3(x)). template struct compose_2_1 : public std::unary_function< typename OP2::argument_type, typename OP1::result_type> { compose_2_1(const OP1& op1, const OP2& op2, const OP3& op3) : op1_(op1) , op2_(op2) , op3_(op3) {} typename OP1::result_type operator()(const typename OP2::argument_type& x) const { return op1_(op2_(x), op3_(x)); } protected: OP1 op1_; OP2 op2_; OP3 op3_; }; /*! * A template helper function used to construct objects of type compose_2_1, * where the component types are based on the data types passed as parameters. */ template inline compose_2_1 compose2(const OP1& op1, const OP2& op2, const OP3& op3) { return compose_2_1(op1, op2, op3); } //! A binary operator function that returns OP1(OP2(x), OP3(y)). template struct compose_2_2 : public std::binary_function< typename OP2::argument_type, typename OP3::argument_type, typename OP1::result_type> { compose_2_2(const OP1& op1 = OP1(), const OP2& op2 = OP2(), const OP3& op3 = OP3()) : op1_(op1) , op2_(op2) , op3_(op3) {} typename OP1::result_type operator()(const typename OP2::argument_type& x, const typename OP3::argument_type& y) const { return op1_(op2_(x), op3_(y)); } protected: OP1 op1_; OP2 op2_; OP3 op3_; }; /*! * A template helper function used to construct objects of type compose_2_2, * where the component types are based on the data types passed as parameters. */ template inline compose_2_2 compose22(const OP1& op1, const OP2& op2, const OP3& op3) { return compose_2_2(op1, op2, op3); } //! TODO: replace with std::is_sorted once we switch to C++11 template bool isSorted(ForwardIterator first, ForwardIterator last, Compare comp) { if (first != last) { for (ForwardIterator n = first; ++n != last; ++first) { if (comp(*n, *first)) return false; } } return true; } //! Possible ownership operations. struct Ownership_t { enum Type { Retain = 0, Acquire = 1 }; }; //! A smart pointer that optionally owns its pointee. template class SingleOwnerPtr { public: SingleOwnerPtr() : ptr_(0) {} explicit SingleOwnerPtr(T* ptr, Ownership_t::Type t = Ownership_t::Acquire) : ptr_(uintp(ptr) | uintp(t == Ownership_t::Acquire)) { } ~SingleOwnerPtr() { *this = 0; } bool is_owner() const { return test_bit(ptr_, 0); } T* get() const { return (T*)clear_bit(ptr_, 0); } T& operator*() const { return *get(); } T* operator->() const { return get(); } SingleOwnerPtr& operator=(T* ptr) { reset(ptr); return *this; } void swap(SingleOwnerPtr& o) { std::swap(ptr_, o.ptr_); } T* release() { store_clear_bit(ptr_, 0); return get(); } T* acquire() { store_set_bit(ptr_, 0); return get(); } void reset(T* x) { if (x != get() && is_owner()) { D deleter; deleter(release()); } ptr_ = set_bit(uintp(x),0); } private: SingleOwnerPtr(const SingleOwnerPtr&); SingleOwnerPtr& operator=(const SingleOwnerPtr&); uintp ptr_; }; template class FlaggedPtr { public: FlaggedPtr() : ptr_(0) {} explicit FlaggedPtr(T* ptr, bool sf = false) : ptr_(uintp(ptr)) { if (sf) flag(); } bool flagged() const { return test_bit(ptr_, 0); } T* get() const { return (T*)clear_bit(ptr_, 0); } T& operator*() const { return *get(); } T* operator->() const { return get(); } void swap(FlaggedPtr& o) { std::swap(ptr_, o.ptr_); } void flag() { store_set_bit(ptr_, 0); } void unflag() { store_clear_bit(ptr_, 0); } private: uintp ptr_; }; template inline FlaggedPtr make_flagged(T* ptr, bool setFlag) { return FlaggedPtr(ptr, setFlag); } //! A (numerical) range represented by a low and a high value. template struct Range { Range(T x, T y) : lo(x), hi(y) { if (x > y) { hi = x; lo = y; } } T clamp(T val) const { if (val < lo) return lo; if (val > hi) return hi; return val; } T lo; T hi; }; template inline bool operator==(const Range& lhs, const Range& rhs) { return lhs.lo == rhs.lo && lhs.hi == rhs.hi; } //! An iterator type for iterating over a range of numerical values. template struct num_iterator : std::iterator { explicit num_iterator(const T& val) : val_(val) {} typedef typename std::iterator::value_type value_type; typedef typename std::iterator::difference_type difference_type; bool operator==(const num_iterator& rhs) const { return val_ == rhs.val_; } bool operator!=(const num_iterator& rhs) const { return val_ != rhs.val_; } bool operator<=(const num_iterator& rhs) const { return val_ <= rhs.val_; } bool operator< (const num_iterator& rhs) const { return val_ < rhs.val_; } bool operator>=(const num_iterator& rhs) const { return val_ >= rhs.val_; } bool operator> (const num_iterator& rhs) const { return val_ > rhs.val_; } value_type operator*() const { return val_; } T const* operator->() const { return &val_; } num_iterator& operator++() { ++val_; return *this; } num_iterator operator++(int) { num_iterator t(*this); ++*this; return t; } num_iterator& operator--() { --val_; return *this; } num_iterator operator--(int) { num_iterator t(*this); --*this; return t; } num_iterator& operator+=(difference_type n) { val_ += n; return *this; } num_iterator& operator-=(difference_type n) { val_ -= n; return *this; } num_iterator operator+(difference_type n) const { return num_iterator(static_cast(val_ + n)); } num_iterator operator-(difference_type n) const { return num_iterator(static_cast(val_ - n)); } value_type operator[](difference_type n)const { return val_ + n; } friend num_iterator operator+(difference_type n, num_iterator it) { return num_iterator(it.val_ + n); } private: T val_; }; //@} //! Base class for library events. struct Event { //! Set of known event sources. enum Subsystem { subsystem_facade = 0, subsystem_load = 1, subsystem_prepare = 2, subsystem_solve = 3 }; //! Possible verbosity levels. enum Verbosity { verbosity_quiet = 0, verbosity_low = 1, verbosity_high = 2, verbosity_max = 3 }; explicit Event(Subsystem sys, uint32 evId, Verbosity verbosity) : system(sys), verb(verbosity), op(0), id(evId) {} uint32 system : 2; //!< One of Event::Subsystem - subsystem that produced the event. uint32 verb : 2; //!< One of Event::Verbosity - the verbosity level of this event. uint32 op : 8; //!< Operation that triggered the event. uint32 id : 16;//!< Type id of event. static uint32 nextId(); }; //! CRTP-base class for events of type T that registers an id for type T. template struct Event_t : Event { Event_t(Subsystem sys, Verbosity verb) : Event(sys, id_s, verb) {} static const uint32 id_s; }; template const uint32 Event_t::id_s = Event::nextId(); template const ToType* event_cast(const EvType& ev) { return ev.id == ToType::id_s ? static_cast(&ev) : 0; } } #endif clingo-5.2.2/clasp/clasp/util/multi_queue.h000066400000000000000000000173621320011352300206620ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_MULIT_QUEUE_H_INCLUDED #define CLASP_MULIT_QUEUE_H_INCLUDED #include namespace Clasp { namespace mt { namespace Detail { struct RawNode; typedef Clasp::Atomic_t::type SafeNodePtr; struct RawNode { SafeNodePtr next; }; // Lock-free stack that is NOT ABA-safe by itself struct RawStack { RawStack() { top = static_cast(0); } RawNode* tryPop() { RawNode* n = 0, *next = 0; do { if ((n = top) == 0) { return 0; } // NOTE: // it is the caller's job to guarantee that n is safe // and n->next is ABA-safe at this point. next = n->next; } while (compare_and_swap(top, n, next) != n); return n; } void push(RawNode* n) { RawNode* assumedTop; do { assumedTop = top; n->next = assumedTop; } while (compare_and_swap(top, assumedTop, n) != assumedTop); } SafeNodePtr top; }; struct DefaultDeleter { template void operator()(T& obj) const { (void)obj; obj.~T(); } }; } //! A (base) class for distributing items between n different threads. /*! * Logically, the class maintains n queues, one for each * involved thread. Threads must register themselves by * calling addThread(). The returned handle has then * to be used for publishing and consuming items. */ template class MultiQueue { protected: typedef Detail::RawNode RawNode; typedef Clasp::Atomic_t::type SafeInt; struct Node : Detail::RawNode { explicit Node(uint32 rc, const T& d) : data(d) { next = 0; refs = rc; } SafeInt refs; T data; }; public: typedef Detail::RawNode* ThreadId; //! creates a new object for at most m threads explicit MultiQueue(uint32 m, const Deleter& d = Deleter()) : maxQ_(m), deleter_(d) { head_.next = 0; tail_ = &head_; } uint32 maxThreads() const { return maxQ_; } void reserve(uint32 c) { struct NodeHead : RawNode { SafeInt refs; }; for (uint32 i = 0; i != c; ++i) { free_.push(new (::operator new(sizeof(Node))) NodeHead()); } } //! destroys the object and all unconsumed items ~MultiQueue() { for (Detail::RawNode* x = head_.next; x ; ) { Node* n = toNode(x); x = x->next; deleter_(n->data); ::operator delete(n); } for (Detail::RawNode* x; (x = free_.tryPop()) != 0; ) { ::operator delete(toNode(x)); } } //! adds a new thread to the object /*! * \note Shall be called at most m times * \return A handle identifying the new thread */ ThreadId addThread() { return &head_; } bool hasItems(ThreadId& cId) const { return cId != tail_; } //! tries to consume an item /*! * \pre cId was initially obtained via a call to addThread() * \note tryConsume() is thread-safe w.r.t different ThreadIds */ bool tryConsume(ThreadId& cId, T& out) { if (cId != tail_) { RawNode* n = cId; cId = cId->next; assert(cId != 0 && "MultiQueue is corrupted!"); release(n); out = toNode(cId)->data; return true; } return false; } //! pops an item from the queue associated with the given thread /*! * \pre hasItems(cId) == true */ void pop(ThreadId& cId) { assert(hasItems(cId) && "Cannot pop from empty queue!"); RawNode* n = cId; cId = cId->next; release(n); } protected: //! publishes a new item /*! * \note the function is *not* thread-safe, i.e. * it must not be called concurrently */ void unsafePublish(const T& in, const ThreadId&) { unsafePublish(in); } void unsafePublish(const T& in) { publishRelaxed(allocate(maxQ_, in)); } //! concurrency-safe version of unsafePublish void publish(const T& in, const ThreadId&) { RawNode* newNode = allocate(maxQ_, in); RawNode* assumedTail, *assumedNext; do { assumedTail = tail_; assumedNext = assumedTail->next; if (assumedTail != tail_) { // tail has changed - try again continue; } if (assumedNext != 0) { // someone has added a new node but has not yet // moved the tail - assist him and start over compare_and_swap(tail_, assumedTail, assumedNext); continue; } } while (compare_and_swap(assumedTail->next, static_cast(0), newNode) != 0); // Now that we managed to link a new node to what we think is the current tail // we try to update the tail. If the tail is still what we think it is, // it is moved - otherwise some other thread already did that for us. compare_and_swap(tail_, assumedTail, newNode); } //! Non-atomically adds n to the global queue void publishRelaxed(Node* n) { static_cast(tail_)->next = n; tail_ = n; } uint32 maxQ() const { return maxQ_; } Node* allocate(uint32 maxR, const T& in) { // If the queue is used correctly, the raw stack is ABA-safe at this point. // The ref-counting in the queue makes sure that a node cannot be added back // to the stack while another thread is still in tryPop() - that thread had // not yet the chance to decrease the node's ref count. if (Node* n = toNode(free_.tryPop())) { n->next = 0; n->refs = maxR; new (&n->data)T(in); return n; } return new (::operator new(sizeof(Node))) Node(maxR, in); } private: MultiQueue(const MultiQueue&); MultiQueue& operator=(const MultiQueue&); Node*toNode(Detail::RawNode* x) const { return static_cast(x); } void release(Detail::RawNode* n) { if (n != &head_ && --toNode(n)->refs == 0) { head_.next = static_cast(n->next); deleter_(toNode(n)->data); free_.push(n); } } RawNode head_; Detail::SafeNodePtr tail_; Detail::RawStack free_; const uint32 maxQ_; Deleter deleter_; }; //! Unbounded non-intrusive lock-free multi-producer single consumer queue. /*! * Based on Dmitriy Vyukov's MPSC queue: * http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue */ class MPSCPtrQueue { public: typedef Detail::RawNode RawNode; struct Node : RawNode { void* data; }; typedef Clasp::Atomic_t::type SafeNodePtr; Node* toNode(RawNode* n) const { return static_cast(n); } MPSCPtrQueue() {} void init(Node* sent) { sent->next = 0; sent->data = 0; head_ = sent; tail_ = sent; } bool empty() const { return !static_cast(tail_->next); } void push(Node* n) { n->next = 0; Node* p = head_.exchange(n); p->next = n; } Node* pop() { Node* t = tail_; Node* n = toNode(t->next); if (!n) { return 0; } tail_ = n; t->data = n->data; n->data = 0; return t; } private: MPSCPtrQueue(const MPSCPtrQueue&); MPSCPtrQueue& operator=(const MPSCPtrQueue&); SafeNodePtr head_; // producers char pad_[64 - sizeof(Node*)]; Node* tail_; // consumer }; } } // end namespace Clasp::mt #endif clingo-5.2.2/clasp/clasp/util/pod_vector.h000066400000000000000000000427351320011352300204720ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef BK_LIB_POD_VECTOR_H_INCLUDED #define BK_LIB_POD_VECTOR_H_INCLUDED #include "type_manip.h" #include #include #include #include #include #include namespace bk_lib { namespace detail { template void fill(T* first, T* last, const T& x) { assert(first <= last); switch ((last - first) & 7u) { case 0: while (first != last) { new(first++) T(x); case 7: new(first++) T(x); case 6: new(first++) T(x); case 5: new(first++) T(x); case 4: new(first++) T(x); case 3: new(first++) T(x); case 2: new(first++) T(x); case 1: new(first++) T(x); assert(first <= last); } } } template void copy(Iter first, Iter last, std::size_t s, T* out) { switch (s & 7u) { case 0: while (first != last) { new(out++) T(*first++); case 7: new(out++) T(*first++); case 6: new(out++) T(*first++); case 5: new(out++) T(*first++); case 4: new(out++) T(*first++); case 3: new(out++) T(*first++); case 2: new(out++) T(*first++); case 1: new(out++) T(*first++); } } } template struct Fill { Fill(const T& val) : val_(val) {} void operator()(T* first, std::size_t n) const { detail::fill(first, first + n, val_); } const T& val_; private: Fill& operator=(const Fill&); }; template struct Copy { Copy(Iter first, Iter last) : first_(first), last_(last) {} template void operator()(T* out, std::size_t n) const { detail::copy(first_, last_, n, out); } Iter first_; Iter last_; }; template struct Memcpy { Memcpy(const T* first) : first_(first) {} void operator()(T* out, std::size_t n) const { std::memcpy(out, first_, n*sizeof(T)); } const T* first_; }; typedef char yes_type; typedef char (&no_type)[2]; template struct IterType { static yes_type isPtr(const volatile void*); static no_type isPtr(...); static yes_type isLong(long long); static no_type isLong(...); static T& makeT(); enum { ptr = sizeof(isPtr(makeT())) == sizeof(yes_type) }; enum { num = sizeof(isLong(makeT())) == sizeof(yes_type) }; enum { value = ptr ? 1 : num ? 2 : 0 }; }; } // end namespace bk_lib::detail //! A std::vector-replacement for POD-Types. /*! * \pre T is a POD-Type * \see http://www.comeaucomputing.com/techtalk/#pod for a description of POD-Types. * \note Does not call any destructors and uses std::memcpy to copy/move elements * \note On LP64-machines size and capacity are represented as unsigned integers (instead of e.g. std::size_t) */ template > class pod_vector { public: // types: typedef pod_vector this_type;//not standard typedef Allocator allocator_type; typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; typedef typename Allocator::pointer iterator; typedef typename Allocator::const_pointer const_iterator; typedef typename Allocator::pointer pointer; typedef typename Allocator::const_pointer const_pointer; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; typedef T value_type; typedef typename detail::if_then_else< sizeof(typename Allocator::size_type)<=sizeof(unsigned int), typename Allocator::size_type, unsigned int>::type size_type; typedef typename detail::if_then_else< sizeof(typename Allocator::difference_type)<=sizeof(int), typename Allocator::difference_type, int>::type difference_type; // ctors //! constructs an empty pod_vector. /*! * \post size() == capacity() == 0 */ pod_vector() : ebo_(0, allocator_type()) { } //! constructs an empty pod_vector that uses a copy of a for memory allocations. /*! * \post size() == capacity() == 0 */ explicit pod_vector(const allocator_type& a) : ebo_(0, a) { } //! constructs a pod_vector containing n copies of value. /*! * \post size() == n */ explicit pod_vector(size_type n, const T& value = T(), const allocator_type& a = allocator_type()) : ebo_(n, a) { detail::fill(ebo_.buf, ebo_.buf + n, value); ebo_.size = n; } //! constructs a pod_vector equal to the range [first, last). /*! * \post size() = distance between first and last. */ template pod_vector(Iter first, Iter last, const allocator_type& a = allocator_type(), typename detail::disable_if::num>::type* = 0) : ebo_(0, a) { insert_range(end(), first, last, typename std::iterator_traits::iterator_category()); } //! creates a copy of other /*! * \post size() == other.size() && capacity() == other.size() */ pod_vector(const pod_vector& other) : ebo_(other.size(), other.get_allocator()) { std::memcpy(ebo_.buf, other.begin(), other.size()*sizeof(T)); ebo_.size = other.size(); } pod_vector& operator=(const pod_vector& other) { if (this != &other) { assign(other.begin(), other.end()); } return *this; } //! frees all memory allocated by this pod_vector. /*! * \note Won't call any destructors, because PODs don't have those. */ ~pod_vector() { } /** @name inspectors * inspector-functions */ //@{ //! returns the number of elements currently stored in this pod_vector. size_type size() const { return ebo_.size; } //! size of the largest possible pod_vector size_type max_size() const { typename allocator_type::size_type x = get_allocator().max_size(); std::size_t y = size_type(-1)/sizeof(T); return static_cast(std::min(std::size_t(x), y)); } //! returns the total number of elements this pod_vector can hold without requiring reallocation. size_type capacity() const { return ebo_.cap; } //! returns size() == 0 bool empty() const { return ebo_.size == 0; } const_iterator begin() const { return ebo_.buf; } const_iterator end() const { return ebo_.buf+ebo_.size;} const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } iterator begin() { return ebo_.buf; } iterator end() { return ebo_.buf+ebo_.size; } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } //! returns a copy of the allocator used by this pod_vector allocator_type get_allocator() const { return ebo_; } //@} /** @name elemacc * element access */ //@{ //! returns a reference to the element at position n /*! * \pre n < size() */ reference operator[](size_type n) { assert(n < size()); return ebo_.buf[n]; } //! returns a reference-to-const to the element at position n /*! * \pre n < size() */ const_reference operator[](size_type n) const { assert(n < size()); return ebo_.buf[n]; } //! same as operator[] but throws std::out_of_range if pre-condition is not met. const_reference at(size_type n) const { if (n < size()) return ebo_.buf[n]; throw std::out_of_range("pod_vector::at"); } //! same as operator[] but throws std::out_of_range if pre-condition is not met. reference at(size_type n) { if (n < size()) return ebo_.buf[n]; throw std::out_of_range("pod_vector::at"); } //! equivalent to *begin() reference front() { assert(!empty()); return *ebo_.buf; } //! equivalent to *begin() const_reference front() const { assert(!empty()); return *ebo_.buf; } //! equivalent to *--end() reference back() { assert(!empty()); return ebo_.buf[ebo_.size-1]; } //! equivalent to *--end() const_reference back() const { assert(!empty()); return ebo_.buf[ebo_.size-1]; } //@} /** @name mutators * mutator functions */ //@{ //! erases all elements in the range [begin(), end) /*! * \post size() == 0 */ void clear() { ebo_.size = 0; } void assign(size_type n, const T& val) { clear(); insert(end(), n, val); } template void assign(Iter first, Iter last) { clear(); insert(end(), first, last); } //! erases the element pointed to by pos. /*! * \pre pos != end() && !empty() * \return an iterator pointing to the element following pos (before that element was erased) * of end() if no such element exists. * * \note invalidates all iterators and references referring to elements after pos. */ iterator erase(iterator pos) { assert(!empty() && pos != end()); erase(pos, pos + 1); return pos; } //! erases the elements in the range [first, last) /*! * \pre [first, last) must be a valid range. */ iterator erase(iterator first, iterator last) { if (end() - last > 0) { std::memmove(first, last, (end() - last) * sizeof(T)); } ebo_.size -= static_cast(last - first); return first; } //! adjusts the size of this pod_vector to ns. /*! * resize is equivalent to: * if ns > size insert(end(), ns - size(), val) * if ns < size erase(begin() + ns, end()) * * \post size() == ns */ void resize(size_type ns, const T& val = T()) { if (ns > size()) { ns <= capacity() ? detail::fill(end(), end()+(ns-size()), val) : append_realloc(ns-size(), val); } ebo_.size = ns; } //! reallocates storage if necessary but never changes the size() of this pod_vector. /*! * \note if n is <= capacity() reserve is a noop. Otherwise a reallocation takes place * and capacity() >= n after reserve returned. * \note reallocation invalidates all references, pointers and iterators referring to * elements in this pod_vectror. * * \note when reallocation occurs elements are copied from the old storage using memcpy. */ void reserve(size_type n) { if (n > capacity()) { T* temp = ebo_.allocate(n); std::memcpy(temp, ebo_.buf, size()*sizeof(T)); ebo_.release(); ebo_.buf = temp; ebo_.cap = n; } } void swap(pod_vector& other) { std::swap(ebo_.buf, other.ebo_.buf); std::swap(ebo_.size, other.ebo_.size); std::swap(ebo_.cap, other.ebo_.cap); } //! equivalent to insert(end(), x); void push_back(const T& x) { if (size() < capacity()) { new ((ebo_.buf+ebo_.size++)) T(x); } else { append_realloc(1, x); } } //! equivalent to erase(--end()); /*! * \pre !empty() */ void pop_back() { assert(!empty()); --ebo_.size; } //! inserts a copy of val before pos. /*! * \pre pos is a valid iterator. * \return an iterator pointing to the copy of val that was inserted. * \note if size() + 1 > capacity() reallocation occurs. Otherwise iterators and * references referring to elements before pos remain valid. * */ iterator insert(iterator pos, const T& val) { return insert(pos, (size_type)1, val); } //! inserts n copies of val before pos. /*! * \pre pos is a valid iterator. */ iterator insert(iterator pos, size_type n, const T& val) { size_type off = static_cast(pos-begin()); insert_impl(pos, n, detail::Fill(val)); return ebo_.buf + off; } //! inserts copies of elements in the range [first, last) before pos. /*! * \pre first and last are not iterators into this pod_vector. * \pre pos is a valid iterator. * \note if first and last are pointers, memcpy is used to insert the elements * in the range [first, last) into this container. * */ template void insert(iterator pos, Iter first, Iter last, typename detail::disable_if::num>::type* = 0) { insert_range(pos, first, last, typename std::iterator_traits::iterator_category()); } /** @name nonstd * Non-standard interface */ //@{ //! adjusts the size of this pod_vector to ns. /*! * In contrast to pod_vector::resize this function does not * initializes new elements in case ns > size(). * This reflects the behaviour of built-in arrays of pod-types. * \note * Any access to an unitialized element is illegal unless it is accessed * in order to assign a new value. */ void resize_no_init(size_type ns) { reserve(ns); ebo_.size = ns; } //@} private: size_type grow_size(size_type n) { size_type new_cap = size() + n; assert(new_cap > size() && "pod_vector: max size exceeded!"); assert(new_cap > capacity()); if (new_cap < 4) new_cap = 1 << (new_cap+1); size_type x = (capacity()*3)>>1; if (new_cap < x) new_cap = x; return new_cap; } void append_realloc(size_type n, const T& x) { size_type new_cap = grow_size(n); pointer temp = ebo_.allocate(new_cap); std::memcpy(temp, ebo_.buf, size()*sizeof(T)); detail::fill(temp+size(), temp+size()+n, x); ebo_.release(); ebo_.buf = temp; ebo_.cap = new_cap; ebo_.size+= n; } void move_right(iterator pos, size_type n) { assert( (pos || n == 0) && (ebo_.eos() - pos) >= (int)n); std::memmove(pos + n, pos, (end() - pos) * sizeof(T)); } template void insert_range(iterator pos, It first, It last, std::random_access_iterator_tag, typename detail::disable_if::value == 0 && detail::same_type::value == 0>::type* = 0) { assert( (first < begin() || first >= end()) && "pod_vec::insert(): Precondition violated!"); typename allocator_type::difference_type diff = std::distance(first, last); assert(diff == 0 || (static_cast(size()+diff) > size() && "pod_vector: max size exceeded!")); insert_impl(pos, static_cast(diff), detail::Memcpy(first)); } template void insert_range(iterator pos, It first, It last, std::forward_iterator_tag) { typename allocator_type::difference_type diff = std::distance(first, last); assert(diff == 0 || (static_cast(size()+diff) > size() && "pod_vector: max size exceeded!")); insert_impl(pos, static_cast(diff), detail::Copy(first, last)); } template void insert_range(iterator pos, Iter first, Iter last, std::input_iterator_tag) { pod_vector temp; while (first != last) temp.push_back(*first++); insert(pos, temp.begin(), temp.end()); } // NOTE: template parameter ST should always equal size_type // and is only needed to workaround an internal compiler error // in gcc 3.4.3 template void insert_impl(iterator pos, ST n, const P& pred) { assert(n == 0 || (size()+n) > size() ); if (size()+n <= capacity()) { move_right(pos, n); pred(pos, n); ebo_.size += n; } else { size_type new_cap = grow_size(n); pointer temp = ebo_.allocate(new_cap); size_type prefix = static_cast(pos-begin()); // copy prefix std::memcpy(temp, begin(), prefix*sizeof(T)); // insert new stuff pred(temp+prefix, n); // copy suffix std::memcpy(temp+prefix+n, pos, (end()-pos)*sizeof(T)); ebo_.release(); ebo_.buf = temp; ebo_.size+= n; ebo_.cap = new_cap; } } struct ebo : public Allocator { // empty-base-optimization typedef typename this_type::size_type size_type; typedef typename this_type::allocator_type A; pointer buf; // pointer to array size_type size; // current size (used elements) size_type cap; // max size before regrow ebo(size_type n, const Allocator& a) : Allocator(a), buf(0), size(0), cap(n) { if (n > 0) { buf = A::allocate(n); } } ~ebo() { release(); } void release() { if (buf) A::deallocate(buf, cap); } T* eos() const { return buf + cap; } } ebo_; }; template inline bool operator==(const pod_vector& lhs, const pod_vector& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } template inline bool operator!=(const pod_vector& lhs, const pod_vector& rhs) { return ! (lhs == rhs); } template inline bool operator<(const pod_vector& lhs, const pod_vector& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } template inline bool operator>(const pod_vector& lhs, const pod_vector& rhs) { return rhs < lhs; } template inline bool operator<=(const pod_vector& lhs, const pod_vector& rhs) { return !(rhs < lhs); } template inline bool operator>=(const pod_vector& lhs, const pod_vector& rhs) { return !(lhs < rhs); } template inline void swap(pod_vector& lhs, pod_vector& rhs) { lhs.swap(rhs); } } #endif clingo-5.2.2/clasp/clasp/util/timer.h000066400000000000000000000051521320011352300174360ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_TIMER_H_INCLUDED #define CLASP_TIMER_H_INCLUDED #ifdef _MSC_VER #pragma once #endif /*! * \file * \brief Defines various types for getting absolute times. */ namespace Clasp { //! A type for getting the current process time. struct ProcessTime { static double getTime(); }; //! A type for getting the current thread time. struct ThreadTime { static double getTime(); }; //! A tpe for getting the current wall-clock time. struct RealTime { static double getTime(); }; inline double diffTime(double tEnd, double tStart) { double diff = tEnd - tStart; return diff >= 0 ? diff : 0.0; } //! A class for measuring elapsed time. /*! * \tparam TimeType must provide a single static function * TimeType::getTime() returning an absolute time. */ template class Timer { public: Timer() : start_(0), split_(0), total_(0) {} void start() { start_ = TimeType::getTime(); } void stop() { split(TimeType::getTime()); } void reset() { *this = Timer(); } //! Same as stop(), start(); void lap() { double t; split(t = TimeType::getTime()); start_ = t; } //! Returns the elapsed time (in seconds) for last start-stop cycle. double elapsed() const { return split_; } //! Returns the total elapsed time for all start-stop cycles. double total() const { return total_; } private: void split(double t) { total_ += (split_ = diffTime(t, start_)); } double start_; double split_; double total_; }; } #endif clingo-5.2.2/clasp/clasp/util/type_manip.h000066400000000000000000000113571320011352300204670ustar00rootroot00000000000000// // Copyright (c) 2010-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef BK_LIB_TYPE_MANIP_H_INCLUDED #define BK_LIB_TYPE_MANIP_H_INCLUDED namespace bk_lib { namespace detail { #if (_MSC_VER >= 1300) #define ALIGNOF(PARAM) (__alignof(PARAM)) #elif defined(__GNUC__) #define ALIGNOF(PARAM) (__alignof__(PARAM)) #else template struct align_helper { char x; T y; }; #define ALIGNOF(T) (sizeof(align_helper)-sizeof(T)) #endif // if b then if_type else else_type template struct if_then_else; template struct if_then_else { typedef if_type type; }; template struct if_then_else { typedef else_type type; }; // 1 if T == U, else 0 template struct same_type { enum { value = 0 }; }; template struct same_type { enum { value = 1 }; }; template struct disable_if { typedef bool type; }; template <> struct disable_if { }; // not in list - marks end of type list struct nil_type {}; // list of types - terminated by nil_type template struct type_list { typedef head head_type; typedef tail tail_type; }; // generates a type lits with up to 18 elements template < typename T1 = nil_type, typename T2 = nil_type, typename T3 = nil_type, typename T4 = nil_type, typename T5 = nil_type, typename T6 = nil_type, typename T7 = nil_type, typename T8 = nil_type, typename T9 = nil_type, typename T10 = nil_type, typename T11 = nil_type, typename T12 = nil_type, typename T13 = nil_type, typename T14 = nil_type, typename T15 = nil_type, typename T16 = nil_type, typename T17 = nil_type, typename T18 = nil_type > struct generate_type_list { typedef typename generate_type_list::type tail_type; typedef type_list type; }; template <> struct generate_type_list<> { typedef nil_type type; }; // maps an integer constant to a type template struct int2type { enum { value = i }; }; typedef int2type<0> false_type; typedef int2type<1> true_type; // declared but not defined struct unknown_type; // finds the element in the type list TList that // has the same alignment as X or X if no such element exists template struct max_align; // IF ALIGNOF(X) == ALIGNOF(H) then H // ELSE max_align template struct max_align_aux; // Base case: ALIGNOF(X) == ALIGNOF(H) template struct max_align_aux { typedef H type; }; // Recursive case template struct max_align_aux { typedef typename max_align::type type; }; template struct max_align { typedef X type; }; template struct max_align > { private: enum { x_align = ALIGNOF(X) }; enum { h_align = ALIGNOF(H) }; public: typedef typename max_align_aux(x_align) == static_cast(h_align), X, H, T>::type type; enum { value = sizeof(type) }; }; // computes alignment size (::value) and type (::type) of T template struct align_of { typedef generate_type_list::type align_list; typedef typename max_align::type type; enum { value = max_align::value }; }; #undef ALIGNOF }} #endif clingo-5.2.2/clasp/clasp/weight_constraint.h000066400000000000000000000260661320011352300211030ustar00rootroot00000000000000// // Copyright (c) 2006-2017 Benjamin Kaufmann // // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #ifndef CLASP_SMODELS_CONSTRAINTS_H_INCLUDED #define CLASP_SMODELS_CONSTRAINTS_H_INCLUDED #ifdef _MSC_VER #pragma once #endif #include namespace Clasp { //! Primitive representation of weight constraint literals in normal form. struct WeightLitsRep { //! Transforms the given literals to the normal form expected by WeightConstraint. /*! * The function simplifies lits and bound by removing assigned and * merging duplicate/complementary literals. Furthermore, negative weights and * their literals are inverted, bound is updated accordingly, and literals * are sorted by decreasing weight. */ static WeightLitsRep create(Solver& s, WeightLitVec& lits, weight_t bound); //! Propagates the constraint W == *this. /*! * If *this is always satisfied (bound <= 0) or unsatisfied (bound > reach), * the function forward propagates W. Otherwise, if W is not free, it assigns * (and removes) literals from *this that must hold. */ bool propagate(Solver& s, Literal W); bool sat() const { return bound <= 0; } bool unsat() const { return reach < bound; } bool open() const { return bound > 0 && bound <= reach;} bool hasWeights() const { return size && lits[0].second > 1; } WeightLiteral* lits; /*!< Literals sorted by decreasing weight. */ uint32 size; /*!< Number of literals in lits. */ weight_t bound; /*!< Rhs of linear constraint. */ weight_t reach; /*!< Sum of weights of lits. */ }; //! Class implementing smodels-like cardinality- and weight constraints. /*! * \ingroup constraint * This class represents a constraint of type W == w1*x1 ... wn*xn >= B, * where W and each xi are literals and B and each wi are strictly positive integers. * * The class is used to represent smodels-like weight constraint, i.e. * the body of a basic weight rule. In this case W is the literal associated with the body. * A cardinality constraint is handled like a weight constraint where all weights are equal to 1. * * Given a WeightConstraint with bound \p B and set of literals \p L, * - let \p sumTrue be the sum of the weights of all literals \p l in \p L that are currently true, * - \p sumReach be the sum of the weights of all literals \p l in \p L that are currently not false, and * - \p U be the set of literals \p l in \p L that are currently unassigned * . * the class implements the following four inference rules: * - \b FTB: If \p sumTrue >= \p B: assign \p W to true. * - \b BFB: If \p W is false: set false all literals \p l in \p U for which \p sumTrue + weight(\p l) >= \p B. * - \b FFB: If \p sumReach < \p B: assign \p W to false. * - \b BTB: If \p W is true: set true all literals \p l in \p U for which \p sumReach - weight(\p l) < \p B. * . */ class WeightConstraint : public Constraint { public: //! Flags controlling weight constraint creation. enum CreationFlags { create_explicit = 1u, //!< Force creation of explicit constraint even if size/bound is small. create_no_add = 3u, //!< Do not add constraint to solver db. create_sat = 4u, //!< Force creation even if constraint is always satisfied. create_no_freeze = 8u, //!< Do not freeze variables in constraint. create_no_share =16u, //!< Do not allow sharing of literals between threads. create_eq_bound =32u, //!< Create equality instead of greater-or-equal constraint. create_only_btb =64u, //!< Only create FFB_BTB constraint. create_only_bfb =128u,//!< Only create FTB_BFB constraint. }; //! Type used to communicate result of create(). class CPair { public: CPair() { con[0] = con[1] = 0; } bool ok() const { return con[0] != (WeightConstraint*)0x1 && con[1] != (WeightConstraint*)0x1; } WeightConstraint* first() const { return con[0]; } WeightConstraint* second()const { return con[1]; } private: friend class WeightConstraint; WeightConstraint* con[2]; }; //! Creates a new weight constraint from the given weight literals. /*! * If the right hand side of the weight constraint is initially true/false (FTB/FFB), * W is assigned appropriately but no constraint is created. Otherwise, * the new weight constraint is added to s unless creationFlags contains create_no_add. * * \param s Solver in which the new constraint is to be used. * \param W The literal that is associated with the constraint. * \param lits The literals of the weight constraint. * \param bound The lower bound of the weight constraint. * \param creationFlags Set of CreationFlags to apply. * \note Cardinality constraint are represented as weight constraints with all weights equal to 1. * \note If creationFlags contains create_eq_bound, a constraint W == (lits == bound) is created that * is represented by up to two weight constraints. */ static CPair create(Solver& s, Literal W, WeightLitVec& lits, weight_t bound, uint32 creationFlags = 0); //! Low level creation function. /*! * \note flag create_eq_bound is ignored by this function, that is, this function always creates * a single >= constraint. */ static CPair create(Solver& s, Literal W, WeightLitsRep& rep, uint32 flags); // constraint interface Constraint* cloneAttach(Solver&); bool simplify(Solver& s, bool = false); void destroy(Solver*, bool); PropResult propagate(Solver& s, Literal p, uint32& data); void reason(Solver&, Literal p, LitVec& lits); bool minimize(Solver& s, Literal p, CCMinRecursive* r); void undoLevel(Solver& s); uint32 estimateComplexity(const Solver& s) const; /*! * Logically, we distinguish two constraints: * - FFB_BTB for handling forward false body and backward true body and * - FTB_BFB for handling forward true body and backward false body. * . * Physically, we store the literals in one array: ~W=1, l0=w0,...,ln-1=wn-1. */ enum ActiveConstraint { FFB_BTB = 0, //!< (\p SumW - \p B)+1 [~W=1, l0=w0,..., ln-1=wn-1] FTB_BFB = 1, //!< \p B [ W=1,~l0=w0,...,~ln-1=wn-1] }; /*! * Returns the i'th literal of constraint c, i.e. * - li, iff c == FFB_BTB * - ~li, iff c == FTB_BFB. */ Literal lit(uint32 i, ActiveConstraint c) const { return Literal::fromId( lits_->lit(i).id() ^ c ); } //! Returns the weight of the i'th literal or 1 if constraint is a cardinality constraint. weight_t weight(uint32 i) const { return lits_->weight(i); } //! Returns the number of literals in this constraint (including W). uint32 size() const { return lits_->size(); } //! Returns false if constraint is a cardinality constraint. bool isWeight() const { return lits_->weights(); } // Returns the index of next literal to look at during backward propagation. uint32 getBpIndex() const { return !isWeight() ? 1 : undo_[0].data>>1; } private: static WeightConstraint* doCreate(Solver& s, Literal W, WeightLitsRep& rep, uint32 flags); bool integrateRoot(Solver& s); struct WL { WL(uint32 s, bool shared, bool w); bool shareable() const { return rc != 0; } bool unique() const { return rc == 0 || refCount() == 1; } bool weights() const { return w != 0; } uint32 size() const { return sz; } Literal lit(uint32 i) const { return lits[(i<> 2; } ActiveConstraint constraint() const { return static_cast((data&2) != 0); } uint32 data; }; // Is literal idx contained as reason lit in the undo stack? bool litSeen(uint32 idx) const { return (undo_[idx].data & 1) != 0; } // Mark/unmark literal idx. void toggleLitSeen(uint32 idx) { undo_[idx].data ^= 1; } // Add watch for idx'th literal of c to the solver. void addWatch(Solver& s, uint32 idx, ActiveConstraint c); // Updates bound_[c] and adds an undo watch to the solver if necessary. // Then adds the literal at position idx to the reason set (and the undo stack). void updateConstraint(Solver& s, uint32 level, uint32 idx, ActiveConstraint c); // Returns the starting index of the undo stack. uint32 undoStart() const { return isWeight(); } UndoInfo undoTop() const { assert(up_ != undoStart()); return undo_[up_-1]; } // Returns the decision level of the last assigned literal // or 0 if no literal was assigned yet. uint32 highestUndoLevel(Solver&) const; void setBpIndex(uint32 n); WL* lits_; // literals of constraint uint32 up_ : 27; // undo position; [undoStart(), up_) is the undo stack uint32 ownsLit_: 1; // owns lits_? uint32 active_ : 2; // which of the two sub-constraints is currently unit? uint32 watched_: 2; // which constraint is watched (3 both, 2 ignore, FTB_BFB, FFB_BTB) weight_t bound_[2]; // FFB_BTB: (sumW-bound)+1 / FTB_BFB: bound POTASSCO_WARNING_BEGIN_RELAXED UndoInfo undo_[0]; // undo stack + seen flag for each literal POTASSCO_WARNING_END_RELAXED }; } #endif clingo-5.2.2/clasp/cmake/000077500000000000000000000000001320011352300151435ustar00rootroot00000000000000clingo-5.2.2/clasp/cmake/clasp-config-version.cmake.in000066400000000000000000000013241320011352300226020ustar00rootroot00000000000000# Note: Adapted from Jonathan Müller's blog post on supporting CMake install: # https://foonathan.github.io/blog/2016/03/03/cmake-install.html # # checks version: major must match, minor must be less than or equal set(PACKAGE_VERSION @CLASP_VERSION@) if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@CLASP_VERSION_MAJOR@") if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@CLASP_VERSION_MINOR@") set(PACKAGE_VERSION_EXACT TRUE) elseif(NOT ("@CLASP_VERSION_MAJOR@" EQUAL 0) AND "${PACKAGE_FIND_VERSION_MINOR}" LESS "@CLASP_VERSION_MINOR@") set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() else() set(PACKAGE_VERSION_UNSUITABLE TRUE) endif()clingo-5.2.2/clasp/cmake/clasp-config.cmake.in000066400000000000000000000002421320011352300211150ustar00rootroot00000000000000include("${CMAKE_CURRENT_LIST_DIR}/clasp.cmake") find_package(potassco 1.0 REQUIRED) if(@CLASP_BUILD_WITH_THREADS@) find_package(Threads REQUIRED) endif() clingo-5.2.2/clasp/create-archive.sh000077500000000000000000000007411320011352300173060ustar00rootroot00000000000000#! /bin/bash VERSION=$1 SOURCE=clasp-$VERSION.tar git archive --prefix=clasp-$VERSION/ -o $SOURCE origin/dev echo Running git archive submodules... p=`pwd` && (echo .; git submodule foreach) | while read entering path; do \ temp="${path%\'}"; \ temp="${temp#\'}"; \ path=$temp; \ [ "$path" = "" ] && continue; \ (cd $path && git archive --prefix=clasp-$VERSION/$path/ HEAD > $p/tmp.tar && tar --concatenate --file=$p/$SOURCE $p/tmp.tar && rm $p/tmp.tar); \ done gzip $SOURCE clingo-5.2.2/clasp/doc/000077500000000000000000000000001320011352300146305ustar00rootroot00000000000000clingo-5.2.2/clasp/doc/api/000077500000000000000000000000001320011352300154015ustar00rootroot00000000000000clingo-5.2.2/clasp/doc/api/clasp.doxy000066400000000000000000003116221320011352300174150ustar00rootroot00000000000000# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = libclasp # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 3.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = potassco-logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 2 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= NO # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = "layout.xml" # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file($line): $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = clasp.txt \ ../../clasp \ ../../clasp/cli \ ../../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = ../../examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the # cost of reduced performance. This can be particularly helpful with template # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was # compiled with the --with-libclang option. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = NO # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra stylesheet files is of importance (e.g. the last # stylesheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = "layout.css" # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /

`: cmake -H. -B cmake --build The following options can be used to configure the installation: CMAKE_INSTALL_PREFIX : install path prefix LIB_POTASSCO_INSTALL_LIB: whether or not to install libpotassco For example, to install lpconvert and libpotassco under `/home/`: cmake -H. -B -DCMAKE_INSTALL_PREFIX=/home/ -DLIB_POTASSCO_INSTALL_LIB=ON cmake --build --target install To use libpotassco in a cmake-based project either: - Place the library inside your project, e.g. using [git submodules](http://git-scm.com/docs/git-submodule). - Call `add_subdirectory()`. or, if libpotassco is installed in `CMAKE_PREFIX_PATH`: - Call `find_package(potassco . CONFIG)`. Finally, call `target_link_libraries(your_target PUBLIC potassco)` to link to the potassco library. ## Documentation Source code documentation can be generated with [Doxygen][doxygen]. Either explicitly: cd doc/ doxygen or via the `doc_potassco` target when using cmake. [aspif]: http://www.cs.uni-potsdam.de/wv/pdfformat/gekakaosscwa16b.pdf "Aspif specification" [cmake]: https://cmake.org/ [doxygen]: http://www.stack.nl/~dimitri/doxygen/ clingo-5.2.2/clasp/libpotassco/app/000077500000000000000000000000001320011352300171655ustar00rootroot00000000000000clingo-5.2.2/clasp/libpotassco/app/CMakeLists.txt000066400000000000000000000005211320011352300217230ustar00rootroot00000000000000add_executable(lpconvert lpconvert.cpp) target_link_libraries(lpconvert libpotassco) set_target_properties(lpconvert PROPERTIES FOLDER exe) if (NOT CMAKE_INSTALL_BINDIR) message(STATUS "BINDIR not set - using bin") set(CMAKE_INSTALL_BINDIR "bin") endif() install(TARGETS lpconvert EXPORT lpconvert DESTINATION ${CMAKE_INSTALL_BINDIR}) clingo-5.2.2/clasp/libpotassco/app/lpconvert.cpp000066400000000000000000000107431320011352300217120ustar00rootroot00000000000000// // Copyright (c) 2015-2017 Benjamin Kaufmann // // This file is part of Potassco. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // #include #include #include #include #include #include #include #include #include using namespace Potassco::ProgramOptions; class LpConvert : public Potassco::Application { public: virtual const char* getName() const { return "lpconvert"; } virtual const char* getVersion() const { return "1.0.0"; } virtual PosOption getPositional() const { return &positional; } virtual const char* getUsage() const { return "[options] []\n" "Convert program in or standard input"; } virtual void initOptions(OptionContext& root); virtual void validateOptions(const OptionContext&, const ParsedOptions&, const ParsedValues&) {} virtual void setup() {} virtual void run(); virtual void printVersion() { Potassco::Application::printVersion(); printf("libpotassco version %s\n", LIB_POTASSCO_VERSION); printf("Copyright (C) Benjamin Kaufmann\n"); printf("License: The MIT License \n"); fflush(stdout); } private: static bool positional(const std::string&, std::string& optOut) { optOut = "input"; return true; } static int error(int line, const char* what) { fprintf(stderr, "*** ERROR: In line %d: %s\n", line, what); static_cast(Application::getInstance())->exit(EXIT_FAILURE); return EXIT_FAILURE; } std::string input_; std::string output_; bool potassco_; bool filter_; bool text_; }; void LpConvert::initOptions(OptionContext& root) { OptionGroup convert("Conversion Options"); convert.addOptions() ("input,i,@2", storeTo(input_), "Input file") ("potassco,p", flag(potassco_ = false), "Enable potassco extensions") ("filter,f" , flag(filter_ = false), "Hide converted potassco predicates") ("output,o" , storeTo(output_)->arg(""), "Write output to (default: stdout)") ("text,t" , flag(text_ = false), "Convert to ground text format") ; root.add(convert); } void LpConvert::run() { std::ifstream iFile; std::ofstream oFile; if (!input_.empty() && input_ != "-") { iFile.open(input_.c_str()); POTASSCO_EXPECT(iFile.is_open(), "Could not open input file!"); } if (!output_.empty() && output_ != "-") { POTASSCO_EXPECT(input_ != output_, "Input and output must be different!"); oFile.open(output_.c_str()); POTASSCO_EXPECT(oFile.is_open(), "Could not open output file!"); } std::istream& in = iFile.is_open() ? iFile : std::cin; std::ostream& os = oFile.is_open() ? oFile : std::cout; Potassco::AspifTextOutput text(os); POTASSCO_EXPECT(in.peek() == 'a' || std::isdigit(in.peek()), "Unrecognized input format!"); if (in.peek() == 'a') { Potassco::SmodelsOutput writer(os, potassco_, 0); Potassco::SmodelsConvert smodels(writer, potassco_); Potassco::readAspif(in, !text_ ? static_cast(smodels) : text, &error); } else { Potassco::AspifOutput aspif(os); Potassco::SmodelsInput::Options opts; if (potassco_) { opts.enableClaspExt().convertEdges().convertHeuristic(); if (filter_) { opts.dropConverted(); } } Potassco::readSmodels(in, !text_? static_cast(aspif) : text, &error, opts); } iFile.close(); oFile.close(); } int main(int argc, char** argv) { LpConvert app; return app.main(argc, argv); } clingo-5.2.2/clasp/libpotassco/cmake/000077500000000000000000000000001320011352300174655ustar00rootroot00000000000000clingo-5.2.2/clasp/libpotassco/cmake/potassco-config-version.cmake.in000066400000000000000000000013671320011352300256640ustar00rootroot00000000000000# Note: Adapted from Jonathan Müller's blog post on supporting CMake install: # https://foonathan.github.io/blog/2016/03/03/cmake-install.html # # checks version: major must match, minor must be less than or equal set(PACKAGE_VERSION @LIB_POTASSCO_VERSION@) if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@LIB_POTASSCO_VERSION_MAJOR@") if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@LIB_POTASSCO_VERSION_MINOR@") set(PACKAGE_VERSION_EXACT TRUE) elseif(NOT ("@LIB_POTASSCO_VERSION_MAJOR@" EQUAL 0) AND "${PACKAGE_FIND_VERSION_MINOR}" LESS "@LIB_POTASSCO_VERSION_MINOR@") set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() else() set(PACKAGE_VERSION_UNSUITABLE TRUE) endif()clingo-5.2.2/clasp/libpotassco/cmake/potassco-config.cmake000066400000000000000000000000651320011352300235660ustar00rootroot00000000000000include("${CMAKE_CURRENT_LIST_DIR}/potassco.cmake") clingo-5.2.2/clasp/libpotassco/doc/000077500000000000000000000000001320011352300171525ustar00rootroot00000000000000clingo-5.2.2/clasp/libpotassco/doc/Doxyfile000066400000000000000000003153421320011352300206700ustar00rootroot00000000000000# Doxyfile 1.8.11 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "libpotassco" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = potassco-logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = "." # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = libpotassco # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = layout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = ../potassco # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, # *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 2 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = "layout.css" # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /