From: mudathirmahgoub Date: Fri, 22 Oct 2021 00:22:00 +0000 (-0500) Subject: Add missing methods to Solver.java (#7299) X-Git-Tag: cvc5-1.0.0~1009 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f9de5395d78bc5338ca800e539e91795730cbd29;p=cvc5.git Add missing methods to Solver.java (#7299) A life of solver object was simple before summer. Then it got complicated with getDifficulty, optional proofs getProof, more assumptions addSygusAssume, and finally different options to choose from OptionInfo. This PR attempts to prepare solver objects for this new life. --- diff --git a/src/api/cpp/cvc5.h b/src/api/cpp/cvc5.h index 7375b16de..57c3f311d 100644 --- a/src/api/cpp/cvc5.h +++ b/src/api/cpp/cvc5.h @@ -2692,7 +2692,7 @@ class CVC5_EXPORT DriverOptions /** * Holds some description about a particular option, including its name, its - * aliases, whether the option was explcitly set by the user, and information + * aliases, whether the option was explicitly set by the user, and information * concerning its value. The `valueInfo` member holds any of the following * alternatives: * - VoidInfo if the option holds no value (or the value has no native type) diff --git a/src/api/java/CMakeLists.txt b/src/api/java/CMakeLists.txt index d6759ba6e..df35390ea 100644 --- a/src/api/java/CMakeLists.txt +++ b/src/api/java/CMakeLists.txt @@ -50,6 +50,7 @@ include(UseJava) set(JAVA_FILES ${CMAKE_CURRENT_LIST_DIR}/cvc5/AbstractPointer.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/CVC5ApiException.java + ${CMAKE_CURRENT_LIST_DIR}/cvc5/CVC5ApiOptionException.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/CVC5ApiRecoverableException.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/Datatype.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/DatatypeConstructor.java @@ -59,6 +60,7 @@ set(JAVA_FILES ${CMAKE_CURRENT_LIST_DIR}/cvc5/Grammar.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/IPointer.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/Op.java + ${CMAKE_CURRENT_LIST_DIR}/cvc5/OptionInfo.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/Pair.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/Result.java ${CMAKE_CURRENT_LIST_DIR}/cvc5/RoundingMode.java @@ -115,12 +117,15 @@ add_library(cvc5jni SHARED jni/cvc5_DatatypeSelector.cpp jni/cvc5_Grammar.cpp jni/cvc5_Op.cpp + jni/cvc5_OptionInfo.cpp jni/cvc5_Result.cpp jni/cvc5_Solver.cpp jni/cvc5_Sort.cpp jni/cvc5_Stat.cpp jni/cvc5_Statistics.cpp - jni/cvc5_Term.cpp) + jni/cvc5_Term.cpp + jni/cvc5JavaApi.cpp) + add_dependencies(cvc5jni generate-jni-headers) target_include_directories(cvc5jni PUBLIC ${JNI_INCLUDE_DIRS}) diff --git a/src/api/java/cvc5/CVC5ApiOptionException.java b/src/api/java/cvc5/CVC5ApiOptionException.java new file mode 100644 index 000000000..e792091e1 --- /dev/null +++ b/src/api/java/cvc5/CVC5ApiOptionException.java @@ -0,0 +1,24 @@ +/****************************************************************************** + * Top contributors (to current version): + * Gereon Kremer, Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * The cvc5 java API. + */ + +package cvc5; + +public class CVC5ApiOptionException extends CVC5ApiRecoverableException +{ + public CVC5ApiOptionException(String message) + { + super(message); + } +} diff --git a/src/api/java/cvc5/DatatypeSelector.java b/src/api/java/cvc5/DatatypeSelector.java index 77136173e..014c35de0 100644 --- a/src/api/java/cvc5/DatatypeSelector.java +++ b/src/api/java/cvc5/DatatypeSelector.java @@ -69,7 +69,7 @@ public class DatatypeSelector extends AbstractPointer private native long getUpdaterTerm(long pointer); - /** @return the range sort of this argument. */ + /** @return the range sort of this selector. */ Sort getRangeSort() { long sortPointer = getRangeSort(pointer); diff --git a/src/api/java/cvc5/OptionInfo.java b/src/api/java/cvc5/OptionInfo.java new file mode 100644 index 000000000..7690a1bc1 --- /dev/null +++ b/src/api/java/cvc5/OptionInfo.java @@ -0,0 +1,209 @@ +/****************************************************************************** + * Top contributors (to current version): + * Gereon Kremer, Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * The cvc5 java API. + */ + +package cvc5; + +import java.math.BigInteger; + +/** + * Holds some description about a particular option, including its name, its + * aliases, whether the option was explicitly set by the user, and information + * concerning its value. The `valueInfo` member holds any of the following + * alternatives: + * - VoidInfo if the option holds no value (or the value has no native type) + * - ValueInfo if the option is of type boolean or String, holds the + * current value and the default value. + * - NumberInfo if the option is of type BigInteger or double, holds + * the current and default value, as well as the minimum and maximum. + * - ModeInfo if the option is a mode option, holds the current and default + * values, as well as a list of valid modes. + * Additionally, this class provides convenience functions to obtain the + * current value of an option in a type-safe manner using boolValue(), + * stringValue(), intValue(), and doubleValue(). They assert that + * the option has the respective type and return the current value. + */ +public class OptionInfo extends AbstractPointer +{ + // region construction and destruction + OptionInfo(Solver solver, long pointer) + { + super(solver, pointer); + this.name = getName(pointer); + this.aliases = getAliases(pointer); + this.setByUser = getSetByUser(pointer); + this.baseInfo = getBaseInfo(pointer); + } + + protected static native void deletePointer(long pointer); + + public long getPointer() + { + return pointer; + } + + @Override public void finalize() + { + deletePointer(pointer); + } + + /** + * @return a string representation of this optionInfo. + */ + protected native String toString(long pointer); + + // endregion + + /** Abstract class for OptionInfo values */ + abstract class BaseInfo + { + } + + /** Has the current and the default value */ + public abstract class ValueInfo extends BaseInfo + { + private final T defaultValue; + private final T currentValue; + public ValueInfo(T defaultValue, T currentValue) + { + this.defaultValue = defaultValue; + this.currentValue = currentValue; + } + public T getDefaultValue() + { + return defaultValue; + } + public T getCurrentValue() + { + return currentValue; + } + } + + public class ModeInfo extends ValueInfo + { + private final String[] modes; + + public ModeInfo(String defaultValue, String currentValue, String[] modes) + { + super(defaultValue, currentValue); + this.modes = modes; + } + public String[] getModes() + { + return modes; + } + } + + /** Has no value information */ + public class VoidInfo extends BaseInfo + { + } + + /** Default value, current value, minimum and maximum of a numeric value */ + public class NumberInfo extends ValueInfo + { + private final T minimum; + private final T maximum; + public NumberInfo(T defaultValue, T currentValue, T minimum, T maximum) + { + super(defaultValue, currentValue); + this.minimum = minimum; + this.maximum = maximum; + } + public T getMinimum() + { + return minimum; + } + public T getMaximum() + { + return maximum; + } + } + + private native String getName(long pointer); + + private native String[] getAliases(long pointer); + + private native boolean getSetByUser(long pointer); + + private native BaseInfo getBaseInfo(long pointer); + + /** The option name */ + private final String name; + public String getName() + { + return name; + } + /** The option name aliases */ + private final String[] aliases; + public String[] getAliases() + { + return aliases; + } + /** Whether the option was explicitly set by the user */ + private final boolean setByUser; + public boolean getSetByUser() + { + return setByUser; + } + + /** The option variant information */ + private final BaseInfo baseInfo; + public BaseInfo getBaseInfo() + { + return baseInfo; + } + + /** + * Obtain the current value as a boolean. Asserts that valueInfo holds a boolean. + */ + public boolean booleanValue() + { + return booleanValue(pointer); + } + + private native boolean booleanValue(long pointer); + + /** + * Obtain the current value as a string. Asserts that valueInfo holds a + * string. + */ + public String stringValue() + { + return stringValue(pointer); + } + + private native String stringValue(long pointer); + + /** + * Obtain the current value as as int. Asserts that valueInfo holds an int. + */ + public BigInteger intValue() + { + return intValue(pointer); + } + + private native BigInteger intValue(long pointer); + + /** + * Obtain the current value as a double. Asserts that valueInfo holds a + * double. + */ + public double doubleValue() + { + return doubleValue(pointer); + } + + private native double doubleValue(long pointer); +}; diff --git a/src/api/java/cvc5/Solver.java b/src/api/java/cvc5/Solver.java index c46d60aee..cc5797570 100644 --- a/src/api/java/cvc5/Solver.java +++ b/src/api/java/cvc5/Solver.java @@ -1805,6 +1805,31 @@ public class Solver implements IPointer private native String getOption(long pointer, String option); + /** + * Get all option names that can be used with `setOption`, `getOption` and + * `getOptionInfo`. + * @return all option names + */ + public String[] getOptionNames() + { + return getOptionNames(pointer); + } + + private native String[] getOptionNames(long pointer); + + /** + * Get some information about the given option. Check the `OptionInfo` class + * for more details on which information is available. + * @return information about the given option + */ + public OptionInfo getOptionInfo(String option) + { + long optionPointer = getOptionInfo(pointer, option); + return new OptionInfo(this, optionPointer); + } + + private native long getOptionInfo(long pointer, String option); + /** * Get the set of unsat ("failed") assumptions. * SMT-LIB: @@ -1840,7 +1865,47 @@ public class Solver implements IPointer private native long[] getUnsatCore(long pointer); /** - * Get the value of the given term. + * Get a difficulty estimate for an asserted formula. This method is + * intended to be called immediately after any response to a checkSat. + * + * @return a map from (a subset of) the input assertions to a real value that + * is an estimate of how difficult each assertion was to solve. Unmentioned + * assertions can be assumed to have zero difficulty. + */ + public Map getDifficulty() + { + Map map = getDifficulty(pointer); + Map ret = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) + { + Term key = new Term(this, entry.getKey()); + Term value = new Term(this, entry.getValue()); + ret.put(key, value); + } + return ret; + } + + private native Map getDifficulty(long pointer); + + /** + * Get the refutation proof + * SMT-LIB: + * {@code + * ( get-proof ) + * } + * Requires to enable option 'produce-proofs'. + * @return a string representing the proof, according to the value of + * proof-format-mode. + */ + public String getProof() + { + return getProof(pointer); + } + + private native String getProof(long pointer); + + /** + * Get the value of the given term in the current model. * SMT-LIB: * {@code * ( get-value ( ) ) @@ -1857,7 +1922,7 @@ public class Solver implements IPointer private native long getValue(long pointer, long termPointer); /** - * Get the values of the given terms. + * Get the values of the given terms in the current model. * SMT-LIB: * {@code * ( get-value ( + ) ) @@ -1874,6 +1939,22 @@ public class Solver implements IPointer private native long[] getValue(long pointer, long[] termPointers); + /** + * Get the domain elements of uninterpreted sort s in the current model. The + * current model interprets s as the finite sort whose domain elements are + * given in the return value of this method. + * + * @param s The uninterpreted sort in question + * @return the domain elements of s in the current model + */ + public Term[] getModelDomainElements(Sort s) + { + long[] pointers = getModelDomainElements(pointer, s.getPointer()); + return Utils.getTerms(this, pointers); + } + + private native long[] getModelDomainElements(long pointer, long sortPointer); + /** * This returns false if the model value of free constant v was not essential * for showing the satisfiability of the last call to checkSat using the @@ -2011,6 +2092,26 @@ public class Solver implements IPointer private native long getSeparationNilTerm(long pointer); + /** + * Declare a symbolic pool of terms with the given initial value. + * SMT-LIB: + * {@code + * ( declare-pool ( * ) ) + * } + * @param symbol The name of the pool + * @param sort The sort of the elements of the pool. + * @param initValue The initial value of the pool + */ + public Term declarePool(String symbol, Sort sort, Term[] initValue) + { + long[] termPointers = Utils.getPointers(initValue); + long termPointer = declarePool(pointer, symbol, sort.getPointer(), termPointers); + return new Term(this, termPointer); + } + + private native long declarePool( + long pointer, String symbol, long sortPointer, long[] termPointers); + /** * Pop a level from the assertion stack. * SMT-LIB: @@ -2410,6 +2511,22 @@ public class Solver implements IPointer } private native void addSygusConstraint(long pointer, long termPointer); + + /** + * Add a forumla to the set of Sygus assumptions. + * SyGuS v2: + * {@code + * ( assume ) + * } + * @param term the formula to add as an assumption + */ + public void addSygusAssume(Term term) + { + addSygusAssume(pointer, term.getPointer()); + } + + private native void addSygusAssume(long pointer, long termPointer); + /** * Add a set of Sygus constraints to the current state that correspond to an * invariant synthesis problem. diff --git a/src/api/java/jni/cvc5JavaApi.cpp b/src/api/java/jni/cvc5JavaApi.cpp new file mode 100644 index 000000000..378fa0948 --- /dev/null +++ b/src/api/java/jni/cvc5JavaApi.cpp @@ -0,0 +1,52 @@ +/****************************************************************************** + * Top contributors (to current version): + * Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * The cvc5 Java API. + */ + +#include "cvc5JavaApi.h" + +#include +#include + +jobjectArray getStringArrayFromStringVector( + JNIEnv* env, const std::vector& cStrings) +{ + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray ret = + env->NewObjectArray(cStrings.size(), stringClass, env->NewStringUTF("")); + for (size_t i = 0; i < cStrings.size(); i++) + { + jstring jString = env->NewStringUTF(cStrings[i].c_str()); + env->SetObjectArrayElement(ret, i, jString); + } + return ret; +} + +jobject getDoubleObject(JNIEnv* env, double cValue) +{ + jdouble jValue = static_cast(cValue); + jclass doubleClass = env->FindClass("java/lang/Double"); + jmethodID methodId = env->GetMethodID(doubleClass, "", "(D)V"); + jobject ret = env->NewObject(doubleClass, methodId, jValue); + return ret; +} + +jobject getBooleanObject(JNIEnv* env, bool cValue) +{ + jboolean jValue = static_cast(cValue); + jclass booleanClass = env->FindClass("Ljava/lang/Boolean;"); + jmethodID booleanConstructor = + env->GetMethodID(booleanClass, "", "(Z)V"); + jobject ret = env->NewObject(booleanClass, booleanConstructor, jValue); + return ret; +} \ No newline at end of file diff --git a/src/api/java/jni/cvc5JavaApi.h b/src/api/java/jni/cvc5JavaApi.h index 7b550ef28..73f2fb396 100644 --- a/src/api/java/jni/cvc5JavaApi.h +++ b/src/api/java/jni/cvc5JavaApi.h @@ -13,31 +13,38 @@ * The cvc5 Java API. */ -#include - #ifndef CVC5__JAVA_API_H #define CVC5__JAVA_API_H +#include + +#include +#include + #define CVC5_JAVA_API_TRY_CATCH_BEGIN \ try \ { -#define CVC5_JAVA_API_TRY_CATCH_END(env) \ - } \ - catch (const CVC5ApiRecoverableException& e) \ - { \ - jclass exceptionClass = \ - env->FindClass("cvc5/CVC5ApiRecoverableException"); \ - env->ThrowNew(exceptionClass, e.what()); \ - } \ - catch (const CVC5ApiException& e) \ - { \ - jclass exceptionClass = env->FindClass("cvc5/CVC5ApiException"); \ - env->ThrowNew(exceptionClass, e.what()); \ +#define CVC5_JAVA_API_TRY_CATCH_END(env) \ + } \ + catch (const CVC5ApiOptionException& e) \ + { \ + jclass exceptionClass = env->FindClass("cvc5/CVC5ApiOptionException"); \ + env->ThrowNew(exceptionClass, e.what()); \ + } \ + catch (const CVC5ApiRecoverableException& e) \ + { \ + jclass exceptionClass = \ + env->FindClass("cvc5/CVC5ApiRecoverableException"); \ + env->ThrowNew(exceptionClass, e.what()); \ + } \ + catch (const CVC5ApiException& e) \ + { \ + jclass exceptionClass = env->FindClass("cvc5/CVC5ApiException"); \ + env->ThrowNew(exceptionClass, e.what()); \ } #define CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, returnValue) \ CVC5_JAVA_API_TRY_CATCH_END(env) \ return returnValue; -#endif // CVC5__JAVA_API_H /** * Convert pointers coming from Java to cvc5 objects @@ -83,4 +90,51 @@ jlongArray getPointersFromObjects(JNIEnv* env, const std::vector& objects) jlongArray ret = env->NewLongArray(objects.size()); env->SetLongArrayRegion(ret, 0, objects.size(), pointers.data()); return ret; -} \ No newline at end of file +} + +/** + * Convert a cpp signed (unsigned) integer to an object of BigInteger class + * @tparam T cpp types (int64_t, uint64_t, int32_t, int32_t, etc) + * @param env jni environment + * @param value cpp integer value + * @return an object of java BigInteger + */ +template +jobject getBigIntegerObject(JNIEnv* env, T value) +{ + std::string s = std::to_string(value); + jstring javaString = env->NewStringUTF(s.c_str()); + jclass bigIntegerClass = env->FindClass("java/math/BigInteger"); + jmethodID bigIntegerConstructor = + env->GetMethodID(bigIntegerClass, "", "(Ljava/lang/String;)V"); + jobject ret = + env->NewObject(bigIntegerClass, bigIntegerConstructor, javaString); + return ret; +} + +/** + * Generate an array of java strings from a vector of cpp strings + * @param env jni environment + * @param cStrings a vector of strings + * @return an array of java strings + */ +jobjectArray getStringArrayFromStringVector( + JNIEnv* env, const std::vector& cStrings); + +/** + * Generate a Double object from cpp double value + * @param env jni environment + * @param value + * @return a Double object + */ +jobject getDoubleObject(JNIEnv* env, double value); + +/** + * Generate a Boolean object from cpp bool value + * @param env jni environment + * @param value + * @return a Boolean object + */ +jobject getBooleanObject(JNIEnv* env, bool value); + +#endif // CVC5__JAVA_API_H \ No newline at end of file diff --git a/src/api/java/jni/cvc5_OptionInfo.cpp b/src/api/java/jni/cvc5_OptionInfo.cpp new file mode 100644 index 000000000..c4bcc2e04 --- /dev/null +++ b/src/api/java/jni/cvc5_OptionInfo.cpp @@ -0,0 +1,351 @@ +/****************************************************************************** + * Top contributors (to current version): + * Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * The cvc5 Java API. + */ + +#include "cvc5_OptionInfo.h" + +#include "api/cpp/cvc5.h" +#include "cvc5JavaApi.h" + +using namespace cvc5::api; + +/* + * Class: cvc5_OptionInfo + * Method: deletePointer + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_cvc5_OptionInfo_deletePointer(JNIEnv*, + jclass, + jlong pointer) +{ + delete reinterpret_cast(pointer); +} + +/* + * Class: cvc5_OptionInfo + * Method: toString + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_cvc5_OptionInfo_toString(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + std::stringstream ss; + ss << *current; + return env->NewStringUTF(ss.str().c_str()); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_OptionInfo + * Method: getName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_cvc5_OptionInfo_getName(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + return env->NewStringUTF(current->name.c_str()); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_OptionInfo + * Method: getAliases + * Signature: (J)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_cvc5_OptionInfo_getAliases(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + jobjectArray ret = getStringArrayFromStringVector(env, current->aliases); + return ret; + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_OptionInfo + * Method: getSetByUser + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_cvc5_OptionInfo_getSetByUser(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + return static_cast(current->setByUser); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, static_cast(false)); +} + +/** + * Convert OptionInfo::NumberInfo cpp object to OptionInfo.NumberInfo java + * object + * @tparam T cpp integer types int64_t, uint64_t, etc + * @param env jni environment + * @param optionInfo a java object for this OptionInfo + * @param numberInfoClass the java class for OptionInfo.NumberInfo + * @param methodId a constructor for OptionInfo.NumberInfo + * @param info the cpp OptionInfo::NumberInfo object + * @return a java object of class OptionInfo.NumberInfo + */ +template +jobject getNumberInfoFromInteger(JNIEnv* env, + const _jobject* optionInfo, + jclass numberInfoClass, + jmethodID methodId, + const OptionInfo::NumberInfo& info) +{ + jobject defaultValue = getBigIntegerObject(env, info.defaultValue); + jobject currentValue = getBigIntegerObject(env, info.currentValue); + jobject minimum = nullptr; + if (info.minimum) + { + minimum = getBigIntegerObject(env, *info.minimum); + } + jobject maximum = nullptr; + if (info.maximum) + { + maximum = getBigIntegerObject(env, *info.maximum); + } + jobject ret = env->NewObject(numberInfoClass, + methodId, + optionInfo, + defaultValue, + currentValue, + minimum, + maximum); + + return ret; +} + +template +jobject getNumberInfoFromInteger(JNIEnv* env, + const _jobject* optionInfo, + jclass numberInfoClass, + jmethodID methodId, + const OptionInfo::NumberInfo& info); + +template +jobject getNumberInfoFromInteger(JNIEnv* env, + const _jobject* optionInfo, + jclass numberInfoClass, + jmethodID methodId, + const OptionInfo::NumberInfo& info); + +/* + * Class: cvc5_OptionInfo + * Method: getBaseInfo + * Signature: (J)Lcvc5/BaseInfo; + */ +JNIEXPORT jobject JNICALL Java_cvc5_OptionInfo_getBaseInfo(JNIEnv* env, + jobject optionInfo, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + std::variant, + OptionInfo::ValueInfo, + OptionInfo::NumberInfo, + OptionInfo::NumberInfo, + OptionInfo::NumberInfo, + OptionInfo::ModeInfo> + v = current->valueInfo; + + if (std::holds_alternative(v)) + { + jclass voidInfoClass = env->FindClass("cvc5/OptionInfo$VoidInfo"); + jmethodID methodId = + env->GetMethodID(voidInfoClass, "", "(Lcvc5/OptionInfo;)V"); + jobject ret = env->NewObject(voidInfoClass, methodId, optionInfo); + return ret; + } + + if (std::holds_alternative>(v) + || std::holds_alternative>(v)) + { + jclass valueInfoClass = env->FindClass("cvc5/OptionInfo$ValueInfo"); + jmethodID methodId = env->GetMethodID( + valueInfoClass, + "", + "(Lcvc5/OptionInfo;Ljava/lang/Object;Ljava/lang/Object;)V"); + + if (std::holds_alternative>(v)) + { + auto info = std::get>(v); + jobject currentValue = getBooleanObject(env, info.currentValue); + jobject defaultValue = getBooleanObject(env, info.defaultValue); + jobject ret = env->NewObject( + valueInfoClass, methodId, optionInfo, defaultValue, currentValue); + return ret; + } + + if (std::holds_alternative>(v)) + { + auto info = std::get>(v); + jstring defaultValue = env->NewStringUTF(info.defaultValue.c_str()); + jstring currentValue = env->NewStringUTF(info.currentValue.c_str()); + jobject ret = env->NewObject( + valueInfoClass, methodId, optionInfo, defaultValue, currentValue); + return ret; + } + } + + if (std::holds_alternative>(v) + || std::holds_alternative>(v) + || std::holds_alternative>(v)) + { + jclass numberInfoClass = env->FindClass("cvc5/OptionInfo$NumberInfo"); + jmethodID methodId = + env->GetMethodID(numberInfoClass, + "", + "(Lcvc5/OptionInfo;Ljava/lang/Object;Ljava/lang/" + "Object;Ljava/lang/Object;Ljava/lang/Object;)V"); + + if (std::holds_alternative>(v)) + { + auto info = std::get>(v); + return getNumberInfoFromInteger( + env, optionInfo, numberInfoClass, methodId, info); + } + + if (std::holds_alternative>(v)) + { + auto info = std::get>(v); + return getNumberInfoFromInteger( + env, optionInfo, numberInfoClass, methodId, info); + } + + if (std::holds_alternative>(v)) + { + auto info = std::get>(v); + jobject defaultValue = getDoubleObject(env, info.defaultValue); + jobject currentValue = getDoubleObject(env, info.currentValue); + jobject minimum = nullptr; + if (info.minimum) + { + minimum = getDoubleObject(env, *info.minimum); + } + jobject maximum = nullptr; + if (info.maximum) + { + maximum = getDoubleObject(env, *info.maximum); + } + jobject ret = env->NewObject(numberInfoClass, + methodId, + optionInfo, + defaultValue, + currentValue, + minimum, + maximum); + return ret; + } + } + + if (std::holds_alternative(v)) + { + jclass modeInfoClass = env->FindClass("cvc5/OptionInfo$ModeInfo"); + jmethodID methodId = + env->GetMethodID(modeInfoClass, + "", + "(Lcvc5/OptionInfo;Ljava/lang/String;Ljava/lang/" + "String;[Ljava/lang/String;)V"); + + auto info = std::get(v); + jstring defaultValue = env->NewStringUTF(info.defaultValue.c_str()); + jstring currentValue = env->NewStringUTF(info.currentValue.c_str()); + jobject stringArray = getStringArrayFromStringVector(env, info.modes); + jobject ret = env->NewObject(modeInfoClass, + methodId, + optionInfo, + defaultValue, + currentValue, + stringArray); + return ret; + } + + return nullptr; + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_OptionInfo + * Method: booleanValue + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_cvc5_OptionInfo_booleanValue(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + return static_cast(current->boolValue()); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, static_cast(false)); +} + +/* + * Class: cvc5_OptionInfo + * Method: stringValue + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_cvc5_OptionInfo_stringValue(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + std::string ret = current->stringValue(); + return env->NewStringUTF(ret.c_str()); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_OptionInfo + * Method: intValue + * Signature: (J)Ljava/math/BigInteger; + */ +JNIEXPORT jobject JNICALL Java_cvc5_OptionInfo_intValue(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + std::int64_t value = current->intValue(); + jobject ret = getBigIntegerObject(env, value); + return ret; + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_OptionInfo + * Method: doubleValue + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_cvc5_OptionInfo_doubleValue(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + OptionInfo* current = reinterpret_cast(pointer); + double ret = current->doubleValue(); + return static_cast(ret); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, static_cast(0.0)); +} diff --git a/src/api/java/jni/cvc5_Solver.cpp b/src/api/java/jni/cvc5_Solver.cpp index 53c050c96..cdbb48db0 100644 --- a/src/api/java/jni/cvc5_Solver.cpp +++ b/src/api/java/jni/cvc5_Solver.cpp @@ -1885,6 +1885,57 @@ JNIEXPORT jstring JNICALL Java_cvc5_Solver_getOption(JNIEnv* env, CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0); } +/* + * Class: cvc5_Solver + * Method: getOptionNames + * Signature: (J)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_cvc5_Solver_getOptionNames(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + std::vector options = solver->getOptionNames(); + jobjectArray ret = getStringArrayFromStringVector(env, options); + return ret; + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_Solver + * Method: getOptionInfo + * Signature: (JLjava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_cvc5_Solver_getOptionInfo(JNIEnv* env, + jobject, + jlong pointer, + jstring jOption) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + std::string cOption(env->GetStringUTFChars(jOption, nullptr)); + OptionInfo* ret = new OptionInfo(solver->getOptionInfo(cOption)); + return reinterpret_cast(ret); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0); +} + +/* + * Class: cvc5_Solver + * Method: getDriverOptions + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_cvc5_Solver_getDriverOptions(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + DriverOptions* ret = new DriverOptions(solver->getDriverOptions()); + return reinterpret_cast(ret); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0); +} + /* * Class: cvc5_Solver * Method: getUnsatAssumptions @@ -1919,6 +1970,62 @@ JNIEXPORT jlongArray JNICALL Java_cvc5_Solver_getUnsatCore(JNIEnv* env, CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); } +/* + * Class: cvc5_Solver + * Method: getDifficulty + * Signature: (J)Ljava/util/Map; + */ +JNIEXPORT jobject JNICALL Java_cvc5_Solver_getDifficulty(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + std::map map = solver->getDifficulty(); + // HashMap hashMap = new HashMap(); + jclass hashMapClass = env->FindClass("Ljava/util/HashMap;"); + jmethodID constructor = env->GetMethodID(hashMapClass, "", "()V"); + jobject hashMap = env->NewObject(hashMapClass, constructor); + jmethodID putMethod = env->GetMethodID( + hashMapClass, + "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + // Long longObject = new Long(statPointer) + jclass longClass = env->FindClass("Ljava/lang/Long;"); + jmethodID longConstructor = env->GetMethodID(longClass, "", "(J)V"); + + for (const auto& [k, v] : map) + { + // hashmap.put(key, value); + Term* termKey = new Term(k); + Term* termValue = new Term(v); + jobject key = env->NewObject( + longClass, longConstructor, reinterpret_cast(termKey)); + jobject value = env->NewObject( + longClass, longConstructor, reinterpret_cast(termValue)); + env->CallObjectMethod(hashMap, putMethod, key, value); + } + return hashMap; + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + +/* + * Class: cvc5_Solver + * Method: getProof + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_cvc5_Solver_getProof(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + std::string proof = solver->getProof(); + return env->NewStringUTF(proof.c_str()); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0); +} + /* * Class: cvc5_Solver * Method: getValue @@ -1954,6 +2061,23 @@ JNIEXPORT jlongArray JNICALL Java_cvc5_Solver_getValue__J_3J( CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0); } +/* + * Class: cvc5_Solver + * Method: getModelDomainElements + * Signature: (JJ)[J + */ +JNIEXPORT jlongArray JNICALL Java_cvc5_Solver_getModelDomainElements( + JNIEnv* env, jobject, jlong pointer, jlong sortPointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + Sort* sort = reinterpret_cast(sortPointer); + std::vector terms = solver->getModelDomainElements(*sort); + jlongArray ret = getPointersFromObjects(env, terms); + return ret; + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} + /* * Class: cvc5_Solver * Method: isModelCoreSymbol @@ -2460,6 +2584,23 @@ JNIEXPORT void JNICALL Java_cvc5_Solver_addSygusConstraint(JNIEnv* env, CVC5_JAVA_API_TRY_CATCH_END(env); } +/* + * Class: cvc5_Solver + * Method: addSygusAssume + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_cvc5_Solver_addSygusAssume(JNIEnv* env, + jobject, + jlong pointer, + jlong termPointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Solver* solver = reinterpret_cast(pointer); + Term* term = reinterpret_cast(termPointer); + solver->addSygusAssume(*term); + CVC5_JAVA_API_TRY_CATCH_END(env); +} + /* * Class: cvc5_Solver * Method: addSygusInvConstraint diff --git a/test/unit/api/java/cvc5/SolverTest.java b/test/unit/api/java/cvc5/SolverTest.java index 6f9d8206d..971be58cc 100644 --- a/test/unit/api/java/cvc5/SolverTest.java +++ b/test/unit/api/java/cvc5/SolverTest.java @@ -19,11 +19,11 @@ import static cvc5.Kind.*; import static cvc5.RoundingMode.*; import static org.junit.jupiter.api.Assertions.*; +import java.math.BigInteger; import java.util.*; import java.util.concurrent.atomic.AtomicReference; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.function.Executable; class SolverTest { @@ -1346,6 +1346,75 @@ class SolverTest assertThrows(CVC5ApiException.class, () -> d_solver.getOption("asdf")); } + @Test void getOptionNames() + { + String[] names = d_solver.getOptionNames(); + assertTrue(names.length > 100); + assertTrue(Arrays.asList(names).contains("verbose")); + assertFalse(Arrays.asList(names).contains("foobar")); + } + + @Test void getOptionInfo() + { + List assertions = new ArrayList<>(); + { + assertions.add( + () -> assertThrows(CVC5ApiException.class, () -> d_solver.getOptionInfo("asdf-invalid"))); + } + { + OptionInfo info = d_solver.getOptionInfo("verbose"); + assertions.add(() -> assertEquals("verbose", info.getName())); + assertions.add( + () -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases()))); + assertions.add(() -> assertTrue(info.getBaseInfo() instanceof OptionInfo.VoidInfo)); + } + { + // int64 type with default + OptionInfo info = d_solver.getOptionInfo("verbosity"); + assertions.add(() -> assertEquals("verbosity", info.getName())); + assertions.add( + () -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases()))); + assertions.add( + () -> assertTrue(info.getBaseInfo().getClass() == OptionInfo.NumberInfo.class)); + OptionInfo.NumberInfo numInfo = + (OptionInfo.NumberInfo) info.getBaseInfo(); + assertions.add(() -> assertEquals(0, numInfo.getDefaultValue().intValue())); + assertions.add(() -> assertEquals(0, numInfo.getCurrentValue().intValue())); + assertions.add( + () -> assertFalse(numInfo.getMinimum() != null || numInfo.getMaximum() != null)); + assertions.add(() -> assertEquals(info.intValue().intValue(), 0)); + } + assertAll(assertions); + { + OptionInfo info = d_solver.getOptionInfo("random-freq"); + assertEquals(info.getName(), "random-freq"); + assertEquals( + Arrays.asList(info.getAliases()), Arrays.asList(new String[] {"random-frequency"})); + assertTrue(info.getBaseInfo().getClass() == OptionInfo.NumberInfo.class); + OptionInfo.NumberInfo ni = (OptionInfo.NumberInfo) info.getBaseInfo(); + assertEquals(ni.getCurrentValue(), 0.0); + assertEquals(ni.getDefaultValue(), 0.0); + assertTrue(ni.getMinimum() != null && ni.getMaximum() != null); + assertEquals(ni.getMinimum(), 0.0); + assertEquals(ni.getMaximum(), 1.0); + assertEquals(info.doubleValue(), 0.0); + } + { + // mode option + OptionInfo info = d_solver.getOptionInfo("output"); + assertions.clear(); + assertions.add(() -> assertEquals("output", info.getName())); + assertions.add( + () -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases()))); + assertions.add(() -> assertTrue(info.getBaseInfo().getClass() == OptionInfo.ModeInfo.class)); + OptionInfo.ModeInfo modeInfo = (OptionInfo.ModeInfo) info.getBaseInfo(); + assertions.add(() -> assertEquals("NONE", modeInfo.getDefaultValue())); + assertions.add(() -> assertEquals("OutputTag::NONE", modeInfo.getCurrentValue())); + assertions.add(() -> assertTrue(Arrays.asList(modeInfo.getModes()).contains("NONE"))); + } + assertAll(assertions); + } + @Test void getUnsatAssumptions1() { d_solver.setOption("incremental", "false"); @@ -1388,17 +1457,17 @@ class SolverTest assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatCore()); } - @Test void getUnsatCore3() + @Test void getUnsatCoreAndProof() { d_solver.setOption("incremental", "true"); d_solver.setOption("produce-unsat-cores", "true"); + d_solver.setOption("produce-proofs", "true"); Sort uSort = d_solver.mkUninterpretedSort("u"); Sort intSort = d_solver.getIntegerSort(); Sort boolSort = d_solver.getBooleanSort(); Sort uToIntSort = d_solver.mkFunctionSort(uSort, intSort); Sort intPredSort = d_solver.mkFunctionSort(intSort, boolSort); - Term[] unsat_core; Term x = d_solver.mkConst(uSort, "x"); Term y = d_solver.mkConst(uSort, "y"); @@ -1406,21 +1475,21 @@ class SolverTest Term p = d_solver.mkConst(intPredSort, "p"); Term zero = d_solver.mkInteger(0); Term one = d_solver.mkInteger(1); - Term f_x = d_solver.mkTerm(APPLY_UF, f, x); - Term f_y = d_solver.mkTerm(APPLY_UF, f, y); - Term sum = d_solver.mkTerm(PLUS, f_x, f_y); - Term p_0 = d_solver.mkTerm(APPLY_UF, p, zero); + Term f_x = d_solver.mkTerm(Kind.APPLY_UF, f, x); + Term f_y = d_solver.mkTerm(Kind.APPLY_UF, f, y); + Term sum = d_solver.mkTerm(Kind.PLUS, f_x, f_y); + Term p_0 = d_solver.mkTerm(Kind.APPLY_UF, p, zero); Term p_f_y = d_solver.mkTerm(APPLY_UF, p, f_y); - d_solver.assertFormula(d_solver.mkTerm(GT, zero, f_x)); - d_solver.assertFormula(d_solver.mkTerm(GT, zero, f_y)); - d_solver.assertFormula(d_solver.mkTerm(GT, sum, one)); + d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_x)); + d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_y)); + d_solver.assertFormula(d_solver.mkTerm(Kind.GT, sum, one)); d_solver.assertFormula(p_0); d_solver.assertFormula(p_f_y.notTerm()); assertTrue(d_solver.checkSat().isUnsat()); - AtomicReference atomic = new AtomicReference<>(); - assertDoesNotThrow(() -> atomic.set(d_solver.getUnsatCore())); - unsat_core = atomic.get(); + Term[] unsat_core = d_solver.getUnsatCore(); + + assertDoesNotThrow(() -> d_solver.getProof()); d_solver.resetAssertions(); for (Term t : unsat_core) @@ -1429,6 +1498,42 @@ class SolverTest } Result res = d_solver.checkSat(); assertTrue(res.isUnsat()); + assertDoesNotThrow(() -> d_solver.getProof()); + } + + @Test void getDifficulty() + { + d_solver.setOption("produce-difficulty", "true"); + // cannot ask before a check sat + assertThrows(CVC5ApiException.class, () -> d_solver.getDifficulty()); + d_solver.checkSat(); + assertDoesNotThrow(() -> d_solver.getDifficulty()); + } + + @Test void getDifficulty2() + { + d_solver.checkSat(); + // option is not set + assertThrows(CVC5ApiException.class, () -> d_solver.getDifficulty()); + } + + @Test void getDifficulty3() throws CVC5ApiException + { + d_solver.setOption("produce-difficulty", "true"); + Sort intSort = d_solver.getIntegerSort(); + Term x = d_solver.mkConst(intSort, "x"); + Term zero = d_solver.mkInteger(0); + Term ten = d_solver.mkInteger(10); + Term f0 = d_solver.mkTerm(GEQ, x, ten); + Term f1 = d_solver.mkTerm(GEQ, zero, x); + d_solver.checkSat(); + Map dmap = d_solver.getDifficulty(); + // difficulty should map assertions to integer values + for (Map.Entry t : dmap.entrySet()) + { + assertTrue(t.getKey() == f0 || t.getKey() == f1); + assertTrue(t.getValue().getKind() == Kind.CONST_RATIONAL); + } } @Test void getValue1() @@ -1488,6 +1593,95 @@ class SolverTest assertThrows(CVC5ApiException.class, () -> slv.getValue(x)); } + @Test void getModelDomainElements() + { + d_solver.setOption("produce-models", "true"); + Sort uSort = d_solver.mkUninterpretedSort("u"); + Sort intSort = d_solver.getIntegerSort(); + Term x = d_solver.mkConst(uSort, "x"); + Term y = d_solver.mkConst(uSort, "y"); + Term z = d_solver.mkConst(uSort, "z"); + Term f = d_solver.mkTerm(DISTINCT, x, y, z); + d_solver.assertFormula(f); + d_solver.checkSat(); + assertDoesNotThrow(() -> d_solver.getModelDomainElements(uSort)); + assertTrue(d_solver.getModelDomainElements(uSort).length >= 3); + assertThrows(CVC5ApiException.class, () -> d_solver.getModelDomainElements(intSort)); + } + + @Test void getModelDomainElements2() + { + d_solver.setOption("produce-models", "true"); + d_solver.setOption("finite-model-find", "true"); + Sort uSort = d_solver.mkUninterpretedSort("u"); + Term x = d_solver.mkVar(uSort, "x"); + Term y = d_solver.mkVar(uSort, "y"); + Term eq = d_solver.mkTerm(EQUAL, x, y); + Term bvl = d_solver.mkTerm(BOUND_VAR_LIST, x, y); + Term f = d_solver.mkTerm(FORALL, bvl, eq); + d_solver.assertFormula(f); + d_solver.checkSat(); + assertDoesNotThrow(() -> d_solver.getModelDomainElements(uSort)); + // a model for the above must interpret u as size 1 + assertTrue(d_solver.getModelDomainElements(uSort).length == 1); + } + + @Test void isModelCoreSymbol() + { + d_solver.setOption("produce-models", "true"); + d_solver.setOption("model-cores", "simple"); + Sort uSort = d_solver.mkUninterpretedSort("u"); + Term x = d_solver.mkConst(uSort, "x"); + Term y = d_solver.mkConst(uSort, "y"); + Term z = d_solver.mkConst(uSort, "z"); + Term zero = d_solver.mkInteger(0); + Term f = d_solver.mkTerm(NOT, d_solver.mkTerm(EQUAL, x, y)); + d_solver.assertFormula(f); + d_solver.checkSat(); + assertTrue(d_solver.isModelCoreSymbol(x)); + assertTrue(d_solver.isModelCoreSymbol(y)); + assertFalse(d_solver.isModelCoreSymbol(z)); + assertThrows(CVC5ApiException.class, () -> d_solver.isModelCoreSymbol(zero)); + } + + @Test void getModel() + { + d_solver.setOption("produce-models", "true"); + Sort uSort = d_solver.mkUninterpretedSort("u"); + Term x = d_solver.mkConst(uSort, "x"); + Term y = d_solver.mkConst(uSort, "y"); + Term z = d_solver.mkConst(uSort, "z"); + Term f = d_solver.mkTerm(NOT, d_solver.mkTerm(EQUAL, x, y)); + d_solver.assertFormula(f); + d_solver.checkSat(); + Sort[] sorts = new Sort[] {uSort}; + Term[] terms = new Term[] {x, y}; + assertDoesNotThrow(() -> d_solver.getModel(sorts, terms)); + Term nullTerm = d_solver.getNullTerm(); + Term[] terms2 = new Term[] {x, y, nullTerm}; + assertThrows(CVC5ApiException.class, () -> d_solver.getModel(sorts, terms2)); + } + + @Test void getModel2() + { + d_solver.setOption("produce-models", "true"); + Sort[] sorts = new Sort[] {}; + Term[] terms = new Term[] {}; + assertThrows(CVC5ApiException.class, () -> d_solver.getModel(sorts, terms)); + } + + @Test void getModel3() + { + d_solver.setOption("produce-models", "true"); + Sort[] sorts = new Sort[] {}; + final Term[] terms = new Term[] {}; + d_solver.checkSat(); + assertDoesNotThrow(() -> d_solver.getModel(sorts, terms)); + Sort integer = d_solver.getIntegerSort(); + Sort[] sorts2 = new Sort[] {integer}; + assertThrows(CVC5ApiException.class, () -> d_solver.getModel(sorts2, terms)); + } + @Test void getQuantifierElimination() { Term x = d_solver.mkVar(d_solver.getBooleanSort(), "x"); @@ -2185,6 +2379,20 @@ class SolverTest assertThrows(CVC5ApiException.class, () -> slv.addSygusConstraint(boolTerm)); } + @Test void addSygusAssume() + { + Term nullTerm = d_solver.getNullTerm(); + Term boolTerm = d_solver.mkBoolean(false); + Term intTerm = d_solver.mkInteger(1); + + assertDoesNotThrow(() -> d_solver.addSygusAssume(boolTerm)); + assertThrows(CVC5ApiException.class, () -> d_solver.addSygusAssume(nullTerm)); + assertThrows(CVC5ApiException.class, () -> d_solver.addSygusAssume(intTerm)); + + Solver slv = new Solver(); + assertThrows(CVC5ApiException.class, () -> slv.addSygusAssume(boolTerm)); + } + @Test void addSygusInvConstraint() throws CVC5ApiException { Sort bool = d_solver.getBooleanSort();