diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dd6a27..cae4ffa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 2.8) project(MOZARTVM) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-support") +option(BUILD_CSS "Builds the constraint subsystem" Yes) + include(ExternalProject) set(ep_base "${CMAKE_BINARY_DIR}/externals") set_property(DIRECTORY PROPERTY "EP_BASE" ${ep_base}) @@ -17,6 +20,14 @@ set(GTEST_BUILD_DIR ${DEFAULT_GTEST_BUILD_DIR} CACHE PATH "Path to GTest build") set(MOZART_GENERATOR_FLAGS "${DEFAULT_MOZART_GENERATOR_FLAGS}" CACHE STRING "Additional flags for the generator parser (clang)") +if (BUILD_CSS) + include(Gecode) + set(MOZART_GENERATOR_FLAGS + "-DVM_HAS_CSS=1" "-I${GECODE_INCLUDES}" ${MOZART_GENERATOR_FLAGS}) + include_directories("${GECODE_INCLUDES}") + message(STATUS "Generator flags: ${MOZART_GENERATOR_FLAGS}") +endif() + add_subdirectory(generator) set(CMAKE_CXX_FLAGS "-Wall -std=c++0x ${CMAKE_CXX_FLAGS}") diff --git a/boostenv/main/CMakeLists.txt b/boostenv/main/CMakeLists.txt index f0be824..f7401ad 100644 --- a/boostenv/main/CMakeLists.txt +++ b/boostenv/main/CMakeLists.txt @@ -25,6 +25,12 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(MOZART_GENERATOR_FLAGS "-I/usr/lib/c++/v1") endif() +if(BUILD_CSS) + list(APPEND MOZART_GENERATOR_FLAGS "-DVM_HAS_CSS=1" "-I${GECODE_INCLUDES}") + include_directories(${GECODE_INCLUDES}) + add_definitions("-DVM_HAS_CSS=1") +endif() + # Mozart VM library include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../vm/main" @@ -81,5 +87,10 @@ add_custom_target(genboostsources # Boost environment library +if(BUILD_CSS) + add_definitions(-DVM_HAS_CSS=1) + include_directories(${GECODE_INCLUDES}) +endif() + add_library(mozartvmboost boostenv.cc boostenvmodules.cc) add_dependencies(mozartvmboost genboostsources) diff --git a/cmake-support/Gecode.cmake b/cmake-support/Gecode.cmake new file mode 100644 index 0000000..79ecda2 --- /dev/null +++ b/cmake-support/Gecode.cmake @@ -0,0 +1,63 @@ +set(DEFAULT_GECODE_INSTALL_DIR "${ep_base}/Install/gecode") +set(GECODE_INSTALL_DIR ${DEFAULT_GECODE_INSTALL_DIR} CACHE PATH + "Path to Gecode installation") + +set(GECODE_VERSION 3.7.3) + +if("${GECODE_INSTALL_DIR}" STREQUAL "${DEFAULT_GECODE_INSTALL_DIR}" AND + NOT EXISTS "${GECODE_INSTALL_DIR}/lib/gecode/kernel.hh") + + message(STATUS "Gecode version ${GECODE_VERSION} will be fetch and built") + set(GECODE_SRC_DIR "${ep_base}/Source/gecode") + set(GECODE_BUILD_DIR "${ep_base}/Build/gecode") + + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_CXX_FLAGS "-stdlib=libc++ ${CMAKE_CXX_FLAGS}") + endif() + + separate_arguments(GECODE_CONFIGURE_ARGS UNIX_COMMAND + "CC=${CMAKE_C_COMPILER} + CXX=${CMAKE_CXX_COMPILER} + CXX_FLAGS=${CMAKE_CXX_FLAGS} + CPPFLAGS=${CMAKE_C_FLAGS} + --enable-static + --disable-shared + --prefix=${GECODE_INSTALL_DIR} + --libdir=${GECODE_INSTALL_DIR}/lib + --disable-gist + --disable-flatzinc + --disable-examples + --disable-qt + --disable-driver + --disable-minimodel" + ) + + ExternalProject_Add( + gecode + URL http://www.gecode.org/download/gecode-${GECODE_VERSION}.tar.gz + SOURCE_DIR ${GECODE_SRC_DIR} + BINARY_DIR ${GECODE_BUILD_DIR} + UPDATE_COMMAND "" + PATCH_COMMAND "" + CONFIGURE_COMMAND ${GECODE_SRC_DIR}/configure + ${GECODE_CONFIGURE_ARGS} + BUILD_COMMAND make -j 4 + INSTALL_COMMAND make install + ) +endif() + +link_directories(${GECODE_INSTALL_DIR}/lib) +set(GECODE_LIBRARIES + gecodesearch + gecodeset + gecodeint + gecodekernel + gecodesupport +) +set(GECODE_INCLUDES ${GECODE_INSTALL_DIR}/include) + +foreach(GECODE_LIB ${GECODE_LIBRARIES}) + add_library(${GECODE_LIB} STATIC IMPORTED) + set_property(TARGET ${GECODE_LIB} PROPERTY + IMPORTED_LOCATION ${GECODE_INSTALL_DIR}/lib/lib${GECODE_LIB}.a) +endforeach() \ No newline at end of file diff --git a/vm/CMakeLists.txt b/vm/CMakeLists.txt index b39cc9a..09e4074 100644 --- a/vm/CMakeLists.txt +++ b/vm/CMakeLists.txt @@ -20,5 +20,6 @@ if("${GTEST_SRC_DIR}" STREQUAL "${DEFAULT_GTEST_SRC_DIR}" AND TEST_COMMAND "" ) endif() + add_subdirectory(main) add_subdirectory(test) diff --git a/vm/main/CMakeLists.txt b/vm/main/CMakeLists.txt index 8e0d571..23c027b 100644 --- a/vm/main/CMakeLists.txt +++ b/vm/main/CMakeLists.txt @@ -54,9 +54,19 @@ add_custom_target(gensources DEPENDS mozart.gen VERBATIM) +if(BUILD_CSS) + add_definitions(-DVM_HAS_CSS=1) + include_directories(${GECODE_INCLUDES}) +endif() + # Build the library add_library(mozartvm emulate.cc memmanager.cc gcollect.cc unify.cc sclone.cc vm.cc coredatatypes.cc coders.cc properties.cc coremodules.cc bootunpickler.cc serializer.cc) add_dependencies(mozartvm gensources) + +if(BUILD_CSS) + add_dependencies(mozartvm ${GECODE_LIBRARIES}) + target_link_libraries(mozartvm ${GECODE_LIBRARIES}) +endif() diff --git a/vm/main/coreatoms-decl.hh b/vm/main/coreatoms-decl.hh index f406181..0e39630 100644 --- a/vm/main/coreatoms-decl.hh +++ b/vm/main/coreatoms-decl.hh @@ -86,6 +86,56 @@ struct CoreAtoms { atom_t spaceAltRange; atom_t spaceMerged; atom_t indexOutOfBounds; + + // Constraint programming + // Integer relation types + atom_t irt_eq; + atom_t irt_nq; + atom_t irt_lq; + atom_t irt_le; + atom_t irt_gq; + atom_t irt_gr; + + // Integer consistency levels + atom_t icl_val; + atom_t icl_bnd; + atom_t icl_dom; + atom_t icl_def; + + // Integer IntVarBranch types + atom_t int_var_none; + atom_t int_var_rnd; + atom_t int_var_degree_min; + atom_t int_var_degree_max; + atom_t int_var_afc_min; + atom_t int_var_min_min; + atom_t int_var_min_max; + atom_t int_var_max_min; + atom_t int_var_max_max; + atom_t int_var_size_min; + atom_t int_var_size_max; + atom_t int_var_size_degree_min; + atom_t int_var_size_degree_max; + atom_t int_var_size_afc_min; + atom_t int_var_size_afc_max; + atom_t int_var_regret_min_min; + atom_t int_var_regret_min_max; + atom_t int_var_regret_max_min; + atom_t int_var_regret_max_max; + + // Integer IntValBranch types + atom_t int_val_min; + atom_t int_val_med; + atom_t int_val_max; + atom_t int_val_rad; + atom_t int_val_split_min; + atom_t int_val_split_max; + atom_t int_val_range_min; + atom_t int_val_range_max; + atom_t int_values_min; + atom_t int_values_max; + + }; } diff --git a/vm/main/coreatoms.hh b/vm/main/coreatoms.hh index 7d9f885..cbd2338 100644 --- a/vm/main/coreatoms.hh +++ b/vm/main/coreatoms.hh @@ -74,6 +74,50 @@ void CoreAtoms::initialize(VM vm, AtomTable& atomTable) { spaceAltRange = atomTable.get(vm, MOZART_STR("spaceAltRange")); spaceMerged = atomTable.get(vm, MOZART_STR("spaceMerged")); indexOutOfBounds = atomTable.get(vm, MOZART_STR("indexOutOfBounds")); + + irt_eq = atomTable.get(vm, MOZART_STR("IRT_EQ")); + irt_nq = atomTable.get(vm, MOZART_STR("IRT_NQ")); + irt_lq = atomTable.get(vm, MOZART_STR("IRT_LQ")); + irt_le = atomTable.get(vm, MOZART_STR("IRT_LE")); + irt_gq = atomTable.get(vm, MOZART_STR("IRT_GQ")); + irt_gr = atomTable.get(vm, MOZART_STR("IRT_GR")); + + icl_val = atomTable.get(vm, MOZART_STR("ICL_VAL")); + icl_bnd = atomTable.get(vm, MOZART_STR("ICL_BND")); + icl_dom = atomTable.get(vm, MOZART_STR("ICL_DOM")); + icl_def = atomTable.get(vm, MOZART_STR("ICL_DEF")); + + int_var_none = atomTable.get(vm, MOZART_STR("INT_VAR_NONE")); + int_var_rnd = atomTable.get(vm, MOZART_STR("INT_VAR_RND")); + int_var_degree_min = atomTable.get(vm, MOZART_STR("INT_VAR_DEGREE_MIN")); + int_var_degree_max = atomTable.get(vm, MOZART_STR("INT_VAR_DEGREE_MAX")); + int_var_afc_min = atomTable.get(vm, MOZART_STR("INT_VAR_AFC_MIN")); + int_var_min_min = atomTable.get(vm, MOZART_STR("INT_VAR_MIN_MIN")); + int_var_min_max = atomTable.get(vm, MOZART_STR("INT_VAR_MIN_MAX")); + int_var_max_min = atomTable.get(vm, MOZART_STR("INT_VAR_MAX_MIN")); + int_var_max_max = atomTable.get(vm, MOZART_STR("INT_VAR_MAX_MAX")); + int_var_size_min = atomTable.get(vm, MOZART_STR("INT_VAR_SIZE_MIN")); + int_var_size_max = atomTable.get(vm, MOZART_STR("INT_VAR_SIZE_MAX")); + int_var_size_degree_min = atomTable.get(vm, MOZART_STR("INT_VAR_SIZE_DEGREE_MIN")); + int_var_size_degree_max = atomTable.get(vm, MOZART_STR("INT_VAR_SIZE_DEGREE_MAX")); + int_var_size_afc_min = atomTable.get(vm, MOZART_STR("INT_VAR_SIZE_AFC_MIN")); + int_var_size_afc_max = atomTable.get(vm, MOZART_STR("INT_VAR_SIZE_AFC_MAX")); + int_var_regret_min_min = atomTable.get(vm, MOZART_STR("INT_VAR_REGRET_MIN_MIN")); + int_var_regret_min_max = atomTable.get(vm, MOZART_STR("INT_VAR_REGRET_MIN_MAX")); + int_var_regret_max_min = atomTable.get(vm, MOZART_STR("INT_VAR_REGRET_MAX_MIN")); + int_var_regret_max_max = atomTable.get(vm, MOZART_STR("INT_VAR_REGRET_MAX_MAX")); + + int_val_min = atomTable.get(vm, MOZART_STR("INT_VAL_MIN")); + int_val_med = atomTable.get(vm, MOZART_STR("INT_VAL_MED")); + int_val_max = atomTable.get(vm, MOZART_STR("INT_VAL_MAX")); + int_val_rad = atomTable.get(vm, MOZART_STR("INT_VAL_RND")); + int_val_split_min = atomTable.get(vm, MOZART_STR("INT_VAL_SPLIT_MIN")); + int_val_split_max = atomTable.get(vm, MOZART_STR("INT_VAL_SPLIT_MAX")); + int_val_range_min = atomTable.get(vm, MOZART_STR("INT_VAL_RANGE_MIN")); + int_val_range_max = atomTable.get(vm, MOZART_STR("INT_VAL_RANGE_MAX")); + int_values_min = atomTable.get(vm, MOZART_STR("INT_VALUES_MIN")); + int_values_max = atomTable.get(vm, MOZART_STR("INT_VALUES_MAX")); + } } diff --git a/vm/main/coredatatypes-decl.hh b/vm/main/coredatatypes-decl.hh index 1109a40..6d45ce7 100644 --- a/vm/main/coredatatypes-decl.hh +++ b/vm/main/coredatatypes-decl.hh @@ -56,5 +56,9 @@ #include "string-decl.hh" #include "unit-decl.hh" #include "variables-decl.hh" - +//#ifdef VM_HAS_CSS +#include "cstintvar-decl.hh" +#include "cstsetvar-decl.hh" +#include "cstboolvar-decl.hh" +//#endif #endif // __COREDATATYPES_DECL_H diff --git a/vm/main/coredatatypes.hh b/vm/main/coredatatypes.hh index 8b0aa8b..713c150 100644 --- a/vm/main/coredatatypes.hh +++ b/vm/main/coredatatypes.hh @@ -56,5 +56,10 @@ #include "string.hh" #include "unit.hh" #include "variables.hh" +//#ifdef VM_HAS_CSS +#include "cstintvar.hh" +#include "cstsetvar.hh" +#include "cstboolvar.hh" +//#endif #endif // __COREDATATYPES_H diff --git a/vm/main/coreinterfaces-decl.hh b/vm/main/coreinterfaces-decl.hh index b81f39d..8bfc43e 100644 --- a/vm/main/coreinterfaces-decl.hh +++ b/vm/main/coreinterfaces-decl.hh @@ -568,6 +568,17 @@ struct Interface: void killSpace(RichNode self, VM vm) { raiseTypeError(vm, MOZART_STR("Space"), self); } + + void injectSpace(RichNode self, VM vm, RichNode callable) { + raiseTypeError(vm, MOZART_STR("Space"), self); + } + +#ifdef VM_HAS_CSS + void info(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("Space"), self); + } +#endif + }; class ThreadLike; @@ -669,6 +680,96 @@ struct Interface: } }; +#ifdef VM_HAS_CSS +class ConstraintVar; +template <> +struct Interface: + ImplementedBy, + NoAutoReflectiveCalls { + + bool assigned(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("ConstraintVar"), self); + } +}; + +class IntVarLike; +template<> +struct Interface: + ImplementedBy, + NoAutoReflectiveCalls { + + bool isIntVarLike(RichNode self, VM vm) { + return false; + } + + Gecode::IntVar& intVar(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("IntVarLike"), self); + } + + UnstableNode min(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("IntVarLike"), self); + } + + UnstableNode max(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("IntVarLike"), self); + } + + UnstableNode value(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("IntVarLike"), self); + } + + UnstableNode isIn(RichNode self, VM vm, RichNode right) { + raiseTypeError(vm, MOZART_STR("IntVarLike"), self); + } +}; + +class SetVarLike; +template<> +struct Interface: + ImplementedBy, + NoAutoReflectiveCalls { + + bool isSetVarLike(RichNode self, VM vm) { + return false; + } + + Gecode::SetVar& setVar(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("SetVarLike"), self); + } +}; + +class BoolVarLike; +template<> +struct Interface: + ImplementedBy, + NoAutoReflectiveCalls { + + bool isBoolVarLike(RichNode self, VM vm) { + return false; + } + + Gecode::BoolVar& boolVar(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("BoolVarLike"), self); + } +}; + +class ConstraintSpace; +template<> +struct Interface: + ImplementedBy, + NoAutoReflectiveCalls { + + bool isConstraintSpace(RichNode self, VM vm) { + return false; + } + + GecodeSpace& constraintSpace(RichNode self, VM vm) { + raiseTypeError(vm, MOZART_STR("ConstraintSpace"), self); + } +}; + +#endif + } #endif // __COREINTERFACES_DECL_H diff --git a/vm/main/coreinterfaces.hh b/vm/main/coreinterfaces.hh index 40c7acb..b44be49 100644 --- a/vm/main/coreinterfaces.hh +++ b/vm/main/coreinterfaces.hh @@ -69,6 +69,14 @@ namespace mozart { #include "ChunkLike-interf.hh" #include "StringLike-interf.hh" +#ifdef VM_HAS_CSS +#include "ConstraintVar-interf.hh" +#include "IntVarLike-interf.hh" +#include "SetVarLike-interf.hh" +#include "BoolVarLike-interf.hh" +#include "ConstraintSpace-interf.hh" +#endif + ////////////// // Callable // ////////////// diff --git a/vm/main/coremodules.cc b/vm/main/coremodules.cc index c38561b..743be46 100644 --- a/vm/main/coremodules.cc +++ b/vm/main/coremodules.cc @@ -70,6 +70,9 @@ void registerCoreModules(VM vm) { registerBuiltinModValue(vm); registerBuiltinModVirtualByteString(vm); registerBuiltinModVirtualString(vm); + registerBuiltinModIntVar(vm); + registerBuiltinModIntVarProp(vm); + registerBuiltinModSearch(vm); } } // namespace mozart diff --git a/vm/main/coremodules.hh b/vm/main/coremodules.hh index ebd3e73..c8f7049 100644 --- a/vm/main/coremodules.hh +++ b/vm/main/coremodules.hh @@ -61,5 +61,8 @@ #include "modules/modvalue.hh" #include "modules/modvirtualbytestring.hh" #include "modules/modvirtualstring.hh" +#include "modules/modintvar.hh" +#include "modules/modpropagators.hh" +#include "modules/modsearch.hh" #endif // __COREMODULES_H diff --git a/vm/main/cstboolvar-decl.hh b/vm/main/cstboolvar-decl.hh new file mode 100644 index 0000000..e727919 --- /dev/null +++ b/vm/main/cstboolvar-decl.hh @@ -0,0 +1,66 @@ +#ifndef __CSTBOOLVAR_DECL_H +#define __CSTBOOLVAR_DECL_H + +#include "mozartcore-decl.hh" + +namespace mozart { + +class CstBoolVar; + +#ifndef MOZART_GENERATOR +#include "CstBoolVar-implem-decl.hh" +#endif + +class CstBoolVar: public WithHome, + public DataType, + public Transient, + public WithVariableBehavior<5> { +public: + CstBoolVar(VM vm, size_t index) + : WithHome(vm), _varIndex(index) {} + + // Constructor from min and max elements in the domain + inline + CstBoolVar(VM vm); + + // TODO: Ask Sebastien about this constructor. The docs says that is needed + // if yes, what is its semantics? + // CstBoolVar(VM vm, SpaceRef home) + // : WithHome(home), _varIndex(0) {} + + CstBoolVar(VM vm, GR gr, CstBoolVar from) + // : WithHome(vm,gr,from->home()), _varIndex(from->_varIndex) {} + : WithHome(vm,gr,from), _varIndex(from._varIndex) {} + +public: + Gecode::BoolVar& getVar(void) { + return home()->getCstSpace().boolVar(_varIndex); + } +public: + // BoolVarLike interface + bool isBoolVarLike(VM vm) { + return true; + } + + Gecode::BoolVar& boolVar(VM vm) { + return getVar(); + } +public: + // Miscellaneous + void printReprToStream(RichNode self, VM vm, std::ostream& out, int depth, int width) { + out << getVar(); + } +private: + // The actual representation of a constraint integer variable is a + // Gecode::BoolVar, here we store the index of an object of that class + // inside an array stored by a Gecode::Space + size_t _varIndex; +};// End class CstBoolVar + +#ifndef MOZART_GENERATOR +#include "CstBoolVar-implem-decl-after.hh" +#endif + +} // End namespace mozart + +#endif // __CSTBOOLVAR_DECL_H diff --git a/vm/main/cstboolvar.hh b/vm/main/cstboolvar.hh new file mode 100644 index 0000000..6acc382 --- /dev/null +++ b/vm/main/cstboolvar.hh @@ -0,0 +1,22 @@ +#ifndef __CSTBOOLVAR_H +#define __CSTBOOLVAR_H + +#include "mozartcore.hh" + +#ifndef MOZART_GENERATOR + +namespace mozart { +#include "CstBoolVar-implem.hh" + +CstBoolVar::CstBoolVar(VM vm) + : WithHome(vm), _varIndex(0) { + auto& sp = home()->getCstSpace(); + _varIndex = sp.newBoolVar(); +} + + +} // mozart + +#endif // MOZART_GENERATOR + +#endif // __CSTBOOLVAR_H diff --git a/vm/main/cstintvar-decl.hh b/vm/main/cstintvar-decl.hh new file mode 100644 index 0000000..16ff642 --- /dev/null +++ b/vm/main/cstintvar-decl.hh @@ -0,0 +1,100 @@ +#ifndef __CSTINTVAR_DECL_H +#define __CSTINTVAR_DECL_H + +#include "mozartcore-decl.hh" + +namespace mozart { + +class CstIntVar; + +#ifndef MOZART_GENERATOR +#include "CstIntVar-implem-decl.hh" +#endif + +class CstIntVar: public WithHome, + public DataType, + public Transient, + public WithVariableBehavior<5> { +public: + //typedef SelfType::Self Self; + + // TODO: uuid is missing + + // TODO: getTypeAtomg is missing + + CstIntVar(VM vm, size_t index) + : WithHome(vm), _varIndex(index) {} + + // Constructor from min and max elements in the domain + inline + CstIntVar(VM vm, RichNode min, RichNode max); + + // Constructor from a list (?) describing the domain + CstIntVar(VM vm, RichNode domain) + : WithHome(vm), _varIndex(0) { + // TODO + assert(false); + } + + // TODO: Ask Sebastien about this constructor. The docs says that is needed + // if yes, what is its semantics? + // CstIntVar(VM vm, SpaceRef home) + // : WithHome(home), _varIndex(0) {} + + CstIntVar(VM vm, GR gr, CstIntVar from) + // : WithHome(vm,gr,from->home()), _varIndex(from->_varIndex) {} + : WithHome(vm,gr,from), _varIndex(from._varIndex) {} + + inline + static bool validAsElement(nativeint x); + +public: + Gecode::IntVar& getVar(void) { + return home()->getCstSpace().intVar(_varIndex); + } +public: + // IntVarLike interface + bool isIntVarLike(VM vm) { + return true; + } + + Gecode::IntVar& intVar(VM vm) { + return getVar(); + } + + inline + UnstableNode min(VM vm); + + inline + UnstableNode max(VM vm); + + inline + UnstableNode value(VM vm); + + inline + UnstableNode isIn(VM vm, RichNode right); +public: + // ConstraintVar interface + inline + bool assigned(VM vm) { + return getVar().assigned(); + } +public: + // Miscellaneous + void printReprToStream(RichNode self, VM vm, std::ostream& out, int depth, int width) { + out << getVar(); + } +private: + // The actual representation of a constraint integer variable is a + // Gecode::IntVar, here we store the index of an object of that class + // inside an array stored by a Gecode::Space + size_t _varIndex; +};// End class CstIntVar + +#ifndef MOZART_GENERATOR +#include "CstIntVar-implem-decl-after.hh" +#endif + +} // End namespace mozart + +#endif // __CSTINTVAR_DECL_H diff --git a/vm/main/cstintvar.hh b/vm/main/cstintvar.hh new file mode 100644 index 0000000..466ca1e --- /dev/null +++ b/vm/main/cstintvar.hh @@ -0,0 +1,72 @@ +#ifndef __CSTINTVAR_H +#define __CSTINTVAR_H + +#include "mozartcore.hh" + +#ifndef MOZART_GENERATOR + +namespace mozart { +#include "CstIntVar-implem.hh" + +CstIntVar::CstIntVar(VM vm, RichNode min, RichNode max) + : WithHome(vm), _varIndex(0) { + + nativeint mn = getArgument(vm,min, MOZART_STR("integer")); + nativeint mx = getArgument(vm,max, MOZART_STR("integer")); + if (!validAsElement(mn)) + raiseTypeError(vm, MOZART_STR("IntVarLike"), mn); + if (!validAsElement(mx)) + raiseTypeError(vm, MOZART_STR("IntVarLike"), mx); + // TODO: learn how to rise errors properly + if (mn > mx) + raiseTypeError(vm, MOZART_STR("IntVarLike"), mx); + + auto& sp = home()->getCstSpace(); + _varIndex = sp.newIntVar((int)mn,(int)mx); +} + +bool CstIntVar::validAsElement(nativeint x) { + // Conceptually this method should return true for any integer. + // As we talk about integer decision variables then any integer n + // will represent the (instantiated) domain [n,n]. + // The practical limitation is that an element in a domain must be in + // a range [min,max]. This limitation is imposed by gecode. max is defined + // as INT_MAX-1 (gecode/int.hh:111) and min is defined as -max. + // From this we can say that an small integer can be part of a domain if and + // only if it is in that range. + + int max = INT_MAX - 1; + int min = -max; + return x <= max && x >= min; +} + +// IntVarLike ------------------------------------------------------------------ + +UnstableNode CstIntVar::min(VM vm) { + return SmallInt::build(vm,getVar().min()); +} + +UnstableNode CstIntVar::max(VM vm) { + return SmallInt::build(vm,getVar().max()); +} + +UnstableNode CstIntVar::value(VM vm) { + //if (!assigned(self,vm)) + // raiseTypeError(vm,MOZART_STR("IntVarLike"),self); + return SmallInt::build(vm,getVar().val()); +} + +UnstableNode CstIntVar::isIn(VM vm, RichNode right) { + nativeint r = getArgument(vm, right, MOZART_STR("integer")); + //if(!CstIntVar::validAsElement(r)) + // raiseTypeError(vm,MOZART_STR("IntVarLike"),self); + int e = (int)r; + return getVar().in(e) ? + Boolean::build(vm,true) : Boolean::build(vm,false); +} + +} // mozart + +#endif // MOZART_GENERATOR + +#endif // __CSTINTVAR_H diff --git a/vm/main/cstsetvar-decl.hh b/vm/main/cstsetvar-decl.hh new file mode 100644 index 0000000..328913f --- /dev/null +++ b/vm/main/cstsetvar-decl.hh @@ -0,0 +1,63 @@ +#ifndef __CSTSETVAR_DECL_H +#define __CSTSETVAR_DECL_H + +#include "mozartcore-decl.hh" + +namespace mozart { + +class CstSetVar; + +#ifndef MOZART_GENERATOR +#include "CstSetVar-implem-decl.hh" +#endif + +class CstSetVar: public WithHome, + public DataType, + public Transient, + public WithVariableBehavior<5> { +public: + CstSetVar(VM vm, size_t index) + : WithHome(vm), _varIndex(index) {} + + // Constructor from min and max elements in the domain + inline + CstSetVar(VM vm); + + + CstSetVar(VM vm, GR gr, CstSetVar from) + // : WithHome(vm,gr,from->home()), _varIndex(from->_varIndex) {} + : WithHome(vm,gr,from), _varIndex(from._varIndex) {} + +public: + Gecode::SetVar& getVar(void) { + return home()->getCstSpace().setVar(_varIndex); + } +public: + // SetVarLike interface + bool isSetVarLike(VM vm) { + return true; + } + + Gecode::SetVar& setVar(VM vm) { + return getVar(); + } + +public: + // Miscellaneous + void printReprToStream(RichNode self, VM vm, std::ostream& out, int depth, int width) { + out << getVar(); + } +private: + // The actual representation of a constraint integer variable is a + // Gecode::SetVar, here we store the index of an object of that class + // inside an array stored by a Gecode::Space + size_t _varIndex; +};// End class CstSetVar + +#ifndef MOZART_GENERATOR +#include "CstSetVar-implem-decl-after.hh" +#endif + +} // End namespace mozart + +#endif // __CSTSETVAR_DECL_H diff --git a/vm/main/cstsetvar.hh b/vm/main/cstsetvar.hh new file mode 100644 index 0000000..a434e45 --- /dev/null +++ b/vm/main/cstsetvar.hh @@ -0,0 +1,23 @@ +#ifndef __CSTSETVAR_H +#define __CSTSETVAR_H + +#include "mozartcore.hh" + +#ifndef MOZART_GENERATOR + +namespace mozart { +#include "CstSetVar-implem.hh" + +CstSetVar::CstSetVar(VM vm) + : WithHome(vm), _varIndex(0) { + + auto& sp = home()->getCstSpace(); + _varIndex = sp.newSetVar(); +} + + +} // mozart + +#endif // MOZART_GENERATOR + +#endif // __CSTSETVAR_H diff --git a/vm/main/gecode-space-decl.hh b/vm/main/gecode-space-decl.hh new file mode 100644 index 0000000..f2f0034 --- /dev/null +++ b/vm/main/gecode-space-decl.hh @@ -0,0 +1,97 @@ +#ifndef VM_HAS_CSS +#error This file is only included with the CSS support +#endif + +// temporal!! +#include + +#include +#include +#include +#include + +namespace mozart { +class GecodeSpace : public Gecode::Space { +private: + std::vector _intVars; + std::vector _setVars; + std::vector _boolVars; +public: + GecodeSpace(void) + : Gecode::Space(){ + std::cout << "Constructed gecode space" << std::endl; + } + + GecodeSpace(bool share, GecodeSpace& other) + : Gecode::Space(share,other), + _intVars(other._intVars), + _setVars(other._setVars) + { + for(auto i = _intVars.size(); i--;) + _intVars[i].update(*this,share,other._intVars[i]); + for(auto i = _setVars.size(); i--;) + _setVars[i].update(*this,share,other._setVars[i]); + } + + virtual ~GecodeSpace(void) { + std::cout << "Destructed gecode space" << std::endl; + } + + int propagate(void){ + //std::cout << "GecodeSpace: propagating... " << std::endl; + return (int)(this->status()); + } + //This methods updates all the vars of *this* gecodeSpace with + //the information available in *other* gecodeSpace. + void reflectVars(GecodeSpace& other){ + for(unsigned int i = 0; i<_intVars.size(); ++i) + _intVars[i].update(*this,false,other._intVars[i]); + /*for(auto i = _setVars.size(); i--;) + _setVars[i].update(*this,share,other._setVars[i]);*/ + } + + virtual Gecode::Space* copy(bool share) { + return new GecodeSpace(share,*this); + } + + Gecode::IntVar& intVar(size_t index) { + if (index >= _intVars.size()) + std::cerr << "Accessing intVar at invalid index" << std::endl; + return _intVars[index]; + } + + size_t newIntVar(int min, int max) { + _intVars.push_back(Gecode::IntVar(*this,min,max)); + return _intVars.size() - 1; + } + + Gecode::SetVar& setVar(size_t index) { + if (index >= _setVars.size()) + std::cerr << "Accessing setVar at invalid index" << std::endl; + return _setVars[index]; + } + size_t newSetVar() { + _setVars.push_back(Gecode::SetVar()); + return _setVars.size() - 1; + } + Gecode::BoolVar& boolVar(size_t index) { + if (index >= _boolVars.size()) + std::cerr << "Accessing setVar at invalid index" << std::endl; + return _boolVars[index]; + } + size_t newBoolVar() { + _boolVars.push_back(Gecode::BoolVar()); + return _boolVars.size() - 1; + } + void dumpSpaceInformation(void) const { + std::cout << "Space information" + << std::endl + << "\tInteger variables: " << _intVars.size() << std::endl + << "\tset variables: " << _setVars.size() << std::endl; + for(unsigned int i=0; i<_intVars.size(); ++i){ + if(_intVars[i].size()==1) + std::cout << "FD variable in pos " << i+1 << " is assigned to value " << _intVars[i].val() << std::endl; + } + } +}; +} diff --git a/vm/main/modules/modintvar.hh b/vm/main/modules/modintvar.hh new file mode 100644 index 0000000..cbd5af1 --- /dev/null +++ b/vm/main/modules/modintvar.hh @@ -0,0 +1,91 @@ +#ifndef __MODINTVAR_H +#define __MODINTVAR_H + +#include "../mozartcore.hh" + +#ifndef MOZART_GENERATOR + +namespace mozart { +namespace builtins { + +class ModIntVar: public Module { +public: + ModIntVar(): Module("IntVar") {} + + class New: public Builtin { + public: + New(): Builtin("new") {} + + static void call(VM vm, In min, In max, Out result) { + result = CstIntVar::build(vm,min,max); + } + }; + + class Is: public Builtin { + public: + Is(): Builtin("is") {} + + static void call(VM vm, In var, Out result) { + result = build(vm, IntVarLike(var).isIntVarLike(vm)); + } + }; + + class Min: public Builtin { + public: + Min(): Builtin("min") {} + + static void call(VM vm, In var, Out result) { + result = build(vm, IntVarLike(var).min(vm)); + } + }; + + class Max: public Builtin { + public: + Max(): Builtin("max") {} + + static void call(VM vm, In var, Out result) { + result = build(vm, IntVarLike(var).max(vm)); + } + }; + + class Value: public Builtin { + public: + Value(): Builtin("value") {} + + static void call(VM vm, In var, Out result) { + result = build(vm, IntVarLike(var).value(vm)); + } + }; + + class IsIn: public Builtin { + public: + IsIn(): Builtin("isIn") {} + + static void call(VM vm, In var, In n, Out result) { + result = build(vm, IntVarLike(var).isIn(vm,n)); + } + }; + class Inf: public Builtin { + public: + Inf(): Builtin("inf") {} + + static void call(VM vm, Out result) { + result = build(vm, Gecode::Int::Limits::min); + } + }; + + class Sup: public Builtin { + public: + Sup(): Builtin("sup") {} + + static void call(VM vm, Out result) { + result = build(vm, Gecode::Int::Limits::max); + } + }; + +}; +} // builtins +} // mozart + +#endif // MOZART_GENERATOR +#endif // __MODINTVAR_H diff --git a/vm/main/modules/modpropagators.hh b/vm/main/modules/modpropagators.hh new file mode 100644 index 0000000..c8ae6a8 --- /dev/null +++ b/vm/main/modules/modpropagators.hh @@ -0,0 +1,207 @@ +#ifndef __MODINTVARPROP_H +#define __MODINTVARPROP_H + +#include "../mozartcore.hh" +#include + +namespace mozart { + +namespace builtins { + +// Notes: +// - All the constraints are posted in vm->getCurrentSpace() +// TODO: can I assume that the current space is the same space each +// variable belongs to? +class ModIntVarProp: public Module { +public: + ModIntVarProp(): Module("IntVarProp") {} + + static Gecode::IntRelType atomToRelType(VM vm, In r) { + atom_t a = getArgument(vm,r,MOZART_STR("Atom")); + if (a == vm->coreatoms.irt_eq) return Gecode::IRT_EQ; + if (a == vm->coreatoms.irt_nq) return Gecode::IRT_NQ; + if (a == vm->coreatoms.irt_lq) return Gecode::IRT_LQ; + if (a == vm->coreatoms.irt_le) return Gecode::IRT_LE; + if (a == vm->coreatoms.irt_gq) return Gecode::IRT_GQ; + if (a == vm->coreatoms.irt_gr) return Gecode::IRT_GR; + raiseTypeError(vm,MOZART_STR("InvalidRelationType"),r); + return Gecode::IRT_GR; + } + + static Gecode::IntConLevel atomToIntConLevel(VM vm, In l) { + atom_t a = getArgument(vm,l,MOZART_STR("Atom")); + if (a == vm->coreatoms.icl_val) return Gecode::ICL_VAL; + if (a == vm->coreatoms.icl_bnd) return Gecode::ICL_BND; + if (a == vm->coreatoms.icl_dom) return Gecode::ICL_DOM; + if (a == vm->coreatoms.icl_def) return Gecode::ICL_DEF; + raiseTypeError(vm,MOZART_STR("InvalidIntegerConsistencyLevel"),l); + return Gecode::ICL_DEF; + } + + static Gecode::IntVarBranch atomToIntVarBranch(VM vm, In bvar){ + atom_t a = getArgument(vm,bvar,MOZART_STR("Atom")); + if (a == vm->coreatoms.int_var_none) return Gecode::INT_VAR_NONE; + if (a == vm->coreatoms.int_var_rnd) return Gecode::INT_VAR_RND; + if (a == vm->coreatoms.int_var_degree_min) return Gecode::INT_VAR_DEGREE_MIN; + if (a == vm->coreatoms.int_var_degree_max) return Gecode::INT_VAR_DEGREE_MAX; + if (a == vm->coreatoms.int_var_afc_min) return Gecode::INT_VAR_AFC_MIN; + if (a == vm->coreatoms.int_var_min_min) return Gecode::INT_VAR_MIN_MIN; + if (a == vm->coreatoms.int_var_min_max) return Gecode::INT_VAR_MIN_MAX; + if (a == vm->coreatoms.int_var_max_min) return Gecode::INT_VAR_MAX_MIN; + if (a == vm->coreatoms.int_var_max_max) return Gecode::INT_VAR_MAX_MAX; + if (a == vm->coreatoms.int_var_size_min) return Gecode::INT_VAR_SIZE_MIN; + if (a == vm->coreatoms.int_var_size_max) return Gecode::INT_VAR_SIZE_MAX; + if (a == vm->coreatoms.int_var_size_degree_min) return Gecode::INT_VAR_SIZE_DEGREE_MIN; + if (a == vm->coreatoms.int_var_size_degree_max) return Gecode::INT_VAR_SIZE_DEGREE_MAX; + if (a == vm->coreatoms.int_var_size_afc_min) return Gecode::INT_VAR_SIZE_AFC_MIN; + if (a == vm->coreatoms.int_var_size_afc_max) return Gecode::INT_VAR_SIZE_AFC_MAX; + if (a == vm->coreatoms.int_var_regret_min_min) return Gecode::INT_VAR_REGRET_MIN_MIN; + if (a == vm->coreatoms.int_var_regret_min_max) return Gecode::INT_VAR_REGRET_MIN_MAX; + if (a == vm->coreatoms.int_var_regret_max_min) return Gecode::INT_VAR_REGRET_MAX_MIN; + if (a == vm->coreatoms.int_var_regret_max_max) return Gecode::INT_VAR_REGRET_MAX_MAX; + raiseTypeError(vm,MOZART_STR("InvalidIntegerBranchType"),bvar); + return Gecode::INT_VAR_NONE; + } + + static Gecode::IntValBranch atomToIntValBranch(VM vm, In bval){ + atom_t a = getArgument(vm,bval,MOZART_STR("Atom")); + if (a == vm->coreatoms.int_val_min) return Gecode::INT_VAL_MIN; + if (a == vm->coreatoms.int_val_med) return Gecode::INT_VAL_MED; + if (a == vm->coreatoms.int_val_max) return Gecode::INT_VAL_MAX; + if (a == vm->coreatoms.int_val_rad) return Gecode::INT_VAL_RND; + if (a == vm->coreatoms.int_val_split_min) return Gecode::INT_VAL_SPLIT_MIN; + if (a == vm->coreatoms.int_val_split_max) return Gecode::INT_VAL_SPLIT_MAX; + if (a == vm->coreatoms.int_val_range_min) return Gecode::INT_VAL_RANGE_MIN; + if (a == vm->coreatoms.int_val_range_max) return Gecode::INT_VAL_RANGE_MAX; + if (a == vm->coreatoms.int_values_min) return Gecode::INT_VALUES_MIN; + if (a == vm->coreatoms.int_values_max) return Gecode::INT_VALUES_MAX; + raiseTypeError(vm,MOZART_STR("InvalidIntegerBranchType"),bval); + return Gecode::INT_VAL_MIN; + } + + static Gecode::IntVarArgs getIntVarArgs(VM vm, In x){ + size_t width; + + if(x.is()){ + width = x.as().getWidth(); + Gecode::IntVarArgs v(width); + for(unsigned int i=0; i().getElement(i); + UnstableNode a = Reference::build(vm, t); + RichNode tt = a; + assert(tt.is()); + v[i] = IntVarLike(tt.as()).intVar(vm); + } + return v; + }else if(x.is()){ + Gecode::IntVarArgs v; + StableNode* head=x.as().getHead(); + StableNode* tail=x.as().getTail(); + while (true){ + UnstableNode uhead = Reference::build(vm, head); + RichNode rhead = uhead; + assert(rhead.is()); + v << IntVarLike(rhead.as()).intVar(vm); + UnstableNode utail = Reference::build(vm, tail); + RichNode rtail = utail; + if (!rtail.is()){ + break; + } + UnstableNode ncons = Reference::build(vm, tail); + RichNode rncons = ncons; + head=rncons.as().getHead(); + tail=rncons.as().getTail(); + } + return v; + }else { + std::cout << "Args is Record" << std::endl; + width = x.as().getWidth(); + Gecode::IntVarArgs v(width); + for(unsigned int i=0; i().getElement(i); + UnstableNode a = Reference::build(vm, t); + RichNode tt = a; + assert(tt.is()); + v[i] = IntVarLike(tt.as()).intVar(vm); + } + return v; + } + } + + static Gecode::IntArgs getIntArgs(VM vm, In x){ + std::vector v; + StableNode* head=x.as().getHead(); + StableNode* tail=x.as().getTail(); + while (true){ + UnstableNode uhead = Reference::build(vm, head); + RichNode rhead = uhead; + assert(rhead.is()); + nativeint val=rhead.as().value(); + v.push_back((int)(val)); + UnstableNode utail = Reference::build(vm, tail); + RichNode rtail = utail; + if (!rtail.is()){ + break; + } + UnstableNode ncons = Reference::build(vm, tail); + RichNode rncons = ncons; + head=rncons.as().getHead(); + tail=rncons.as().getTail(); + + } + return Gecode::IntArgs(v); + } + + class Rel: public Builtin { + public: + Rel(): Builtin("rel") {} + + static void call(VM vm, In x0, In r, In x1, In icl) { + assert(vm->getCurrentSpace()->hasConstraintSpace()); + GecodeSpace& home = vm->getCurrentSpace()->getCstSpace(); + Gecode::IntRelType rt = atomToRelType(vm,r); + Gecode::rel(home,IntVarLike(x0).intVar(vm),rt,IntVarLike(x1).intVar(vm)); + } + }; + + class Distinct: public Builtin { + public: + Distinct(): Builtin("distinct") {} + + static void call(VM vm, In x) { + assert(vm->getCurrentSpace()->hasConstraintSpace()); + GecodeSpace& home = vm->getCurrentSpace()->getCstSpace(); + Gecode::distinct(home,getIntVarArgs(vm,x)); + } + }; + + class Linear: public Builtin { + public: + Linear(): Builtin("linear") {} + + static void call(VM vm, In v, In x, In r, In c) { + assert(vm->getCurrentSpace()->hasConstraintSpace()); + GecodeSpace& home = vm->getCurrentSpace()->getCstSpace(); + Gecode::IntRelType rt = atomToRelType(vm,r); + assert(c.is()); + nativeint val=c.as().value(); + Gecode::linear(home,getIntArgs(vm,v),getIntVarArgs(vm,x),rt,(int)(val)); + } + }; + + class Branch: public Builtin { + public: + Branch(): Builtin("branch") {} + static void call(VM vm, In x, In bvar, In bval) { + assert(vm->getCurrentSpace()->hasConstraintSpace()); + GecodeSpace& home = vm->getCurrentSpace()->getCstSpace(); + Gecode::IntVarBranch bvart = atomToIntVarBranch(vm,bvar); + Gecode::IntValBranch bvalt = atomToIntValBranch(vm,bval); + Gecode::branch(home,getIntVarArgs(vm,x),bvart,bvalt); + } + }; + +}; // class ModIntVarProp +} // namespace builtins +} // namespace mozart +#endif // __MODINTVARPROP_H diff --git a/vm/main/modules/modsearch.hh b/vm/main/modules/modsearch.hh new file mode 100644 index 0000000..04b338c --- /dev/null +++ b/vm/main/modules/modsearch.hh @@ -0,0 +1,42 @@ +#ifndef __MODSEARCH_H +#define __MODSEARCH_H + +#include "../mozartcore.hh" +#include + +namespace mozart { +namespace builtins { + +/////////////////// +// Search Module // +/////////////////// + +class ModSearch: public Module { +public: + ModSearch(): Module("Search") {} + + class DFS: public Builtin { + public: + DFS(): Builtin("dfs") {} + + static void call(VM vm, In space, Out result) { + if(ConstraintSpace(space).isConstraintSpace(vm)) { + GecodeSpace& gs = ConstraintSpace(space).constraintSpace(vm); + Gecode::DFS e(&gs); + GecodeSpace *sol = e.next(); + //gs = sol; + + //result = SpaceLike(space).cloneSpace(vm); + } + + } + + }; + +}; + +} // namespace builtins +} // namespace mozart +#endif // __MODSEARCH_H + + diff --git a/vm/main/modules/modspace.hh b/vm/main/modules/modspace.hh index 38c8bca..44f784a 100644 --- a/vm/main/modules/modspace.hh +++ b/vm/main/modules/modspace.hh @@ -143,6 +143,27 @@ public: } } }; + + class Inject: public Builtin { + public: + Inject(): Builtin("inject") {} + + static void call(VM vm, In space, In target) { + return SpaceLike(space).injectSpace(vm, target); + } + }; + +#ifdef VM_HAS_CSS + class Info: public Builtin { + public: + Info(): Builtin("info") {} + + static void call(VM vm, In space) { + return SpaceLike(space).info(vm); + } + }; +#endif + }; } diff --git a/vm/main/reifiedspace-decl.hh b/vm/main/reifiedspace-decl.hh index 7bdc0f3..ce7a5b5 100644 --- a/vm/main/reifiedspace-decl.hh +++ b/vm/main/reifiedspace-decl.hh @@ -79,6 +79,21 @@ public: inline void killSpace(RichNode self, VM vm); + + inline + void injectSpace(RichNode self, VM vm, RichNode callable); + +#ifdef VM_HAS_CSS + inline + void info(RichNode self, VM vm); + + inline + bool isConstraintSpace(RichNode self, VM vm); + + GecodeSpace& constraintSpace(RichNode self, VM vm) { + return _space->getCstSpace(); + } +#endif private: SpaceRef _space; }; @@ -131,6 +146,14 @@ public: inline void killSpace(VM vm); + + inline + void injectSpace(VM vm, RichNode callable); + +#ifdef VM_HAS_CSS + inline + void info(VM vm); +#endif }; #ifndef MOZART_GENERATOR @@ -181,6 +204,14 @@ public: inline void killSpace(VM vm); + + inline + void injectSpace(VM vm, RichNode callable); + +#ifdef VM_HAS_CSS + inline + void info(VM vm); +#endif }; #ifndef MOZART_GENERATOR diff --git a/vm/main/reifiedspace.hh b/vm/main/reifiedspace.hh index efda5f0..d58eb17 100644 --- a/vm/main/reifiedspace.hh +++ b/vm/main/reifiedspace.hh @@ -128,11 +128,32 @@ UnstableNode ReifiedSpace::askSpace(RichNode self, VM vm) { if (!space->isAdmissible(vm)) raise(vm, vm->coreatoms.spaceAdmissible, self); - RichNode statusVar = *space->getStatusVar(); +#ifdef VM_HAS_CSS + int gecodeStatus=-1; + if(space->hasConstraintSpace()){ + //Propagate the constraint space associated to this mozart space + gecodeStatus = (space->getCstSpace()).propagate(); + //if the mozart space is failed, then return failed (failed space is strongest than distributable space?) + if (gecodeStatus == 0){//failed space return immediately. + return Atom::build(vm, vm->coreatoms.failed); + } + } +#endif + RichNode statusVar = *space->getStatusVar(); if (matchesTuple(vm, statusVar, vm->coreatoms.succeeded, wildcard())) { +#ifdef VM_HAS_CSS + if(gecodeStatus == 2){ + //if the mozart space is succeded, then return this tuple (distributable space is strongest than succeded space?). + const Gecode::Choice *ch = space->getCstSpace().choice(); + unsigned int all = ch->alternatives(); + //if distributable space then create tuple alternatives(N) + return buildTuple(vm, vm->coreatoms.alternatives, (nativeint)all); + } +#endif return Atom::build(vm, vm->coreatoms.succeeded); } else { + return { vm, statusVar }; } } @@ -187,6 +208,18 @@ void ReifiedSpace::commitSpace(RichNode self, VM vm, RichNode value) { Space* space = getSpace(); +#ifdef VM_HAS_CSS + if(space->hasConstraintSpace()){ + if(space->getCstSpace().branchers()!=0){ + nativeint alt= getArgument(vm,value, MOZART_STR("integer")); + const Gecode::Choice *ch = space->getCstSpace().choice(); + space->getCstSpace().commit(*ch, (unsigned int)alt); + //std::cout << "commit done " << std::endl; + return; + } + } +#endif + if (!space->isAdmissible(vm)) raise(vm, vm->coreatoms.spaceAdmissible); @@ -229,6 +262,34 @@ void ReifiedSpace::killSpace(RichNode self, VM vm) { space->kill(vm); } +void ReifiedSpace::injectSpace(RichNode self, VM vm, RichNode callable) { + Space* space = getSpace(); + space->inject(vm, callable); +} + +#ifdef VM_HAS_CSS + void ReifiedSpace::info(RichNode self, VM vm) { + Space* space = getSpace(); + + if (!space->isAdmissible(vm)) + return raise(vm, vm->coreatoms.spaceAdmissible); + + if(space->hasConstraintSpace()){ + space->getCstSpace().dumpSpaceInformation(); + }else{ + std::cout << "This space has no constraint space..." << std::endl; + } + } + + bool ReifiedSpace::isConstraintSpace(RichNode self, VM vm) { + Space* space = getSpace(); + if(space->hasConstraintSpace()) + return true; + else + return false; + } +#endif + ///////////////// // FailedSpace // ///////////////// @@ -262,6 +323,15 @@ void FailedSpace::killSpace(VM vm) { // nothing to do } +void FailedSpace::injectSpace(VM vm, RichNode callable) { + // nothing to do +} + +#ifdef VM_HAS_CSS + void FailedSpace::info(VM vm) { + // nothing to do + } +#endif ///////////////// // MergedSpace // ///////////////// @@ -295,6 +365,15 @@ void MergedSpace::killSpace(VM vm) { // nothing to do } +void MergedSpace::injectSpace(VM vm, RichNode callable) { + raise(vm, vm->coreatoms.spaceMerged); +} + +#ifdef VM_HAS_CSS + void MergedSpace::info(VM vm) { + // nothing to do + } +#endif } #endif // MOZART_GENERATOR diff --git a/vm/main/smallint-decl.hh b/vm/main/smallint-decl.hh index aeb5243..7f3ee11 100644 --- a/vm/main/smallint-decl.hh +++ b/vm/main/smallint-decl.hh @@ -26,7 +26,7 @@ #define __SMALLINT_DECL_H #include "mozartcore-decl.hh" - +#include namespace mozart { #ifndef MOZART_GENERATOR @@ -117,6 +117,32 @@ public: inline UnstableNode modValue(VM vm, nativeint b); +#ifdef VM_HAS_CSS +public: + // ConstraintVar interface + inline + bool assigned(VM vm); +public: + // IntVarLike interface + inline + bool isIntVarLike(VM vm); + + inline + Gecode::IntVar& intVar(RichNode self, VM vm); + + inline + UnstableNode min(VM vm); + + inline + UnstableNode max(VM vm); + + inline + UnstableNode value(VM vm); + + inline + UnstableNode isIn(VM vm, RichNode right); + +#endif public: // Miscellaneous diff --git a/vm/main/smallint.hh b/vm/main/smallint.hh index 2c3311f..911efc3 100644 --- a/vm/main/smallint.hh +++ b/vm/main/smallint.hh @@ -30,6 +30,10 @@ #include #include +#ifdef VM_HAS_CSS +#include +#endif + #ifndef MOZART_GENERATOR namespace mozart { @@ -186,6 +190,52 @@ UnstableNode SmallInt::modValue(VM vm, nativeint b) { } } +#ifdef VM_HAS_CSS +// ConstraintVar ------------------------------------------------------------ +bool SmallInt::assigned(VM vm) { + if(!isIntVarLike(vm)) + raiseTypeError(vm, MOZART_STR("ConstraintVar"), value()); + return true; +} +// IntVarLike --------------------------------------------------------------- +bool SmallInt::isIntVarLike(VM vm) { + return (Gecode::Int::Limits::min <= value()) && + (value() <= Gecode::Int::Limits::max); +} + + Gecode::IntVar& SmallInt::intVar(RichNode self, VM vm) { + CstIntVar x(vm,self,self); + return x.getVar(); + } + +UnstableNode SmallInt::min(VM vm) { + if(!isIntVarLike(vm)) + raiseTypeError(vm, MOZART_STR("IntVarLike"),value()); + return SmallInt::build(vm,value()); +} + +UnstableNode SmallInt::max(VM vm) { + if(!isIntVarLike(vm)) + raiseTypeError(vm, MOZART_STR("IntVarLike"),value()); + return SmallInt::build(vm,value()); +} + +UnstableNode SmallInt::value(VM vm) { + if(!isIntVarLike(vm)) + raiseTypeError(vm, MOZART_STR("IntVarLike"),value()); + return SmallInt::build(vm,value()); +} + +UnstableNode SmallInt::isIn(VM vm, RichNode right) { + nativeint r = getArgument(vm,right,MOZART_STR("integer")); + if (r < Gecode::Int::Limits::min || r > Gecode::Int::Limits::max) + raiseTypeError(vm,MOZART_STR("IntVarLike"),right); + return r == value() ? + Boolean::build(vm,true) : Boolean::build(vm,false); +} +#endif + + } #endif // MOZART_GENERATOR diff --git a/vm/main/space-decl.hh b/vm/main/space-decl.hh index 10a6577..9e43204 100644 --- a/vm/main/space-decl.hh +++ b/vm/main/space-decl.hh @@ -31,6 +31,10 @@ #include "exceptions-decl.hh" #include "vmallocatedlist-decl.hh" +#ifdef VM_HAS_CSS +#include "gecode-space-decl.hh" +#endif + namespace mozart { struct ScriptEntry { @@ -173,6 +177,9 @@ public: inline void kill(VM vm); + inline + void inject(VM vm, RichNode callable); + // Distributor public: @@ -331,6 +338,28 @@ private: _mark = false; } +#ifdef VM_HAS_CSS +public: + // The gecode constraint space is created only when needed. That need is + // reflected by (for instance) the declaration of a constraint variable. + // This method returns the gecode space associated to the mozart space, + // creating a new on if needed. + + // An important aspect here is that the gecode space uses external memmory. + // That is, memmory that is not managed by the mozart virtual machine. For + // that reason we have to handle the copy and clonning of gecode spaces in + // order to not cause memmory leaks. + GecodeSpace& getCstSpace() { + if (_cstSpace == nullptr) + _cstSpace = new GecodeSpace; + return *_cstSpace; + } + + bool hasConstraintSpace() { + return _cstSpace != nullptr; + } +#endif + // Fields private: @@ -360,6 +389,10 @@ private: SpaceTrail trail; SpaceScript script; + // Gecode space associated with this mozart space +#ifdef VM_HAS_CSS + GecodeSpace* _cstSpace; +#endif /* * Maintaining a counter of threads * Invariants: diff --git a/vm/main/space.hh b/vm/main/space.hh index 86a2563..26f003e 100644 --- a/vm/main/space.hh +++ b/vm/main/space.hh @@ -126,6 +126,10 @@ void Space::constructor(VM vm, bool isTopLevel, Space* parent) { threadCount = 0; cascadedRunnableThreadCount = 0; + +#ifdef VM_HAS_CSS + _cstSpace = nullptr; +#endif } Space::Space(GR gr, Space* from) { @@ -187,6 +191,23 @@ Space::Space(GR gr, Space* from) { assert(cascadedRunnableThreadCount == 0); } #endif + + // constraint space initialization + // TODO: in this constructor Should I create a clone of the constraint + // space that is insidefrom? +#ifdef VM_HAS_CSS + if(from->hasConstraintSpace()){ + assert(_cstSpace==nullptr); + if(!from->getCstSpace().failed()){ + _cstSpace = (GecodeSpace*) from->getCstSpace().clone(false); + }else{ + _cstSpace = nullptr; + } + //_cstSpace->copyVars(from->getCstSpace()); + }else{ + _cstSpace = nullptr; + } +#endif } // Status @@ -264,6 +285,14 @@ bool Space::merge(VM vm, Space* dest) { if (src->cascadedRunnableThreadCount > 0) dest->cascadedRunnableThreadCount += src->cascadedRunnableThreadCount-1; } +#ifdef VM_HAS_CSS + if(src->hasConstraintSpace()){ + //anfelbar@: This is mandatory... I believe. + assert(dest->hasConstraintSpace()); + //anfelbar@: Update all constraint vars of currentSpace. + dest->getCstSpace().reflectVars(src->getCstSpace()); + } +#endif // Merge constraints return src->installThis(/* isMerge = */ true); @@ -298,6 +327,12 @@ void Space::kill(VM vm) { bindStatusVar(vm, build(vm, vm->coreatoms.failed)); } +void Space::inject(VM vm, RichNode callable) { + Space* src = this; + src->clearStatusVar(vm); + ozcalls::asyncOzCall(vm, src, callable, *src->getRootVar()); +} + // Status variable void Space::clearStatusVar(VM vm) { @@ -596,7 +631,6 @@ void Space::createPropagateThreadOnceAndSuspendItOnVar( propagateThread->suspendOnVar(vm, variable); } } - } #endif // MOZART_GENERATOR diff --git a/vm/test/CMakeLists.txt b/vm/test/CMakeLists.txt index 5d1fbd9..813278b 100644 --- a/vm/test/CMakeLists.txt +++ b/vm/test/CMakeLists.txt @@ -28,6 +28,10 @@ set_property(TARGET custom_gtest_main PROPERTY include_directories("${GTEST_SRC_DIR}" "${GTEST_SRC_DIR}/include") # The testing executable +if(BUILD_CSS) + include_directories(${GECODE_INCLUDES}) + add_definitions(-DVM_HAS_CSS=1) +endif() set(VMTEST_SRCS testutils.cc sanitytest.cc smallinttest.cc floattest.cc atomtest.cc gctest.cc) @@ -39,6 +43,11 @@ else() virtualstringtest.cc bytestringtest.cc) endif() +if(BUILD_CSS) + list(APPEND VMTEST_SRCS csttest.cc) + add_definitions("-DVM_HAS_CSS=1") +endif() + add_executable(vmtest ${VMTEST_SRCS}) target_link_libraries(vmtest mozartvm custom_gtest custom_gtest_main) diff --git a/vm/test/csttest.cc b/vm/test/csttest.cc new file mode 100644 index 0000000..85f00f1 --- /dev/null +++ b/vm/test/csttest.cc @@ -0,0 +1,63 @@ +#include "mozart.hh" + +#include +#include +#include "testutils.hh" + +using namespace mozart; + +class CstTest : public MozartTest {}; + +TEST_F(CstTest, SpaceCreation) { + Space *currentSpace = vm->getCurrentSpace(); + GecodeSpace& cst = currentSpace->getCstSpace(); + cst.dumpSpaceInformation(); +} + +TEST_F(CstTest, InvalidElements) { + UnstableNode n = SmallInt::build(vm,INT_MAX); + EXPECT_FALSE(IntVarLike(n).isIntVarLike(vm)); + + UnstableNode o = SmallInt::build(vm,INT_MAX-1); + EXPECT_TRUE(IntVarLike(o).isIntVarLike(vm)); + + UnstableNode p = SmallInt::build(vm,-(INT_MAX-1)); + EXPECT_TRUE(IntVarLike(p).isIntVarLike(vm)); +} + +TEST_F(CstTest, SmallIntIntVarLikeInterface) { + using namespace patternmatching; + + UnstableNode n = SmallInt::build(vm,-1); + + UnstableNode min = IntVarLike(n).min(vm); + EXPECT_EQ_INT(-1,min); + UnstableNode max = IntVarLike(n).max(vm); + EXPECT_EQ_INT(-1,max); + UnstableNode value = IntVarLike(n).value(vm); + EXPECT_EQ_INT(-1,value); + + UnstableNode m = SmallInt::build(vm,-1); + UnstableNode isInM = IntVarLike(n).isIn(vm,m); + EXPECT_TRUE(getArgument(vm,isInM)); + + UnstableNode o = SmallInt::build(vm,0); + UnstableNode isInO = IntVarLike(n).isIn(vm,o); + EXPECT_FALSE(getArgument(vm,isInO)); +} + +TEST_F(CstTest, IntVarLike) { + nativeint x = -5; + UnstableNode xNode = SmallInt::build(vm,x); + EXPECT_TRUE(IntVarLike(xNode).isIntVarLike(vm)); + + // The following test only makes sense in 64 bits architectures + // where a nativeint can store integer bigger than INT_MIN + nativeint out = INT_MIN + 1; + EXPECT_FALSE(CstIntVar::validAsElement(out)); + UnstableNode outNode = SmallInt::build(vm,out); + EXPECT_FALSE(IntVarLike(outNode).isIntVarLike(vm)); + + EXPECT_RAISE(MOZART_STR("IntVarLike"), + CstIntVar::build(vm,outNode,outNode)); +}