Add missing methods to Solver.java (#7299)
authormudathirmahgoub <mudathirmahgoub@gmail.com>
Fri, 22 Oct 2021 00:22:00 +0000 (19:22 -0500)
committerGitHub <noreply@github.com>
Fri, 22 Oct 2021 00:22:00 +0000 (00:22 +0000)
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.

src/api/cpp/cvc5.h
src/api/java/CMakeLists.txt
src/api/java/cvc5/CVC5ApiOptionException.java [new file with mode: 0644]
src/api/java/cvc5/DatatypeSelector.java
src/api/java/cvc5/OptionInfo.java [new file with mode: 0644]
src/api/java/cvc5/Solver.java
src/api/java/jni/cvc5JavaApi.cpp [new file with mode: 0644]
src/api/java/jni/cvc5JavaApi.h
src/api/java/jni/cvc5_OptionInfo.cpp [new file with mode: 0644]
src/api/java/jni/cvc5_Solver.cpp
test/unit/api/java/cvc5/SolverTest.java

index 7375b16de1d635e168c9877380138f4d1da99e8d..57c3f311dfbb80ab91831c04862c3d61aec8c6b1 100644 (file)
@@ -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)
index d6759ba6ee391fac6846183f95e2b0f8462c7bf3..df35390ea32605aa295679f0bf9c1222f31872da 100644 (file)
@@ -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 (file)
index 0000000..e792091
--- /dev/null
@@ -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);
+  }
+}
index 77136173e0beb996d1d914ba737d4a32bf1d1ffe..014c35de06ca802c1ea7ba5d866070c3201bb2e9 100644 (file)
@@ -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 (file)
index 0000000..7690a1b
--- /dev/null
@@ -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<T> 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<String>
+  {
+    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<T> extends ValueInfo<T>
+  {
+    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);
+};
index c46d60aee0d160a27c827a4394c252e5b6690a61..cc57975707a2cd278496c6f5154ef879141e13b7 100644 (file)
@@ -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<Term, Term> getDifficulty()
+  {
+    Map<Long, Long> map = getDifficulty(pointer);
+    Map<Term, Term> ret = new HashMap<>();
+    for (Map.Entry<Long, Long> 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<Long, Long> 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 ( <term> ) )
@@ -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 ( <term>+ ) )
@@ -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 <symbol> <sort> ( <term>* ) )
+   * }
+   * @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 <term> )
+   * }
+   * @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 (file)
index 0000000..378fa09
--- /dev/null
@@ -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 <string>
+#include <vector>
+
+jobjectArray getStringArrayFromStringVector(
+    JNIEnv* env, const std::vector<std::string>& 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<jdouble>(cValue);
+  jclass doubleClass = env->FindClass("java/lang/Double");
+  jmethodID methodId = env->GetMethodID(doubleClass, "<init>", "(D)V");
+  jobject ret = env->NewObject(doubleClass, methodId, jValue);
+  return ret;
+}
+
+jobject getBooleanObject(JNIEnv* env, bool cValue)
+{
+  jboolean jValue = static_cast<jboolean>(cValue);
+  jclass booleanClass = env->FindClass("Ljava/lang/Boolean;");
+  jmethodID booleanConstructor =
+      env->GetMethodID(booleanClass, "<init>", "(Z)V");
+  jobject ret = env->NewObject(booleanClass, booleanConstructor, jValue);
+  return ret;
+}
\ No newline at end of file
index 7b550ef28c040a1fe972858c394d393c9291a1b0..73f2fb396005adb3105766f027c6995566ca2ed1 100644 (file)
  * The cvc5 Java API.
  */
 
-#include <jni.h>
-
 #ifndef CVC5__JAVA_API_H
 #define CVC5__JAVA_API_H
 
+#include <jni.h>
+
+#include <string>
+#include <vector>
+
 #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<T>& 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 <class T>
+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, "<init>", "(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<std::string>& 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 (file)
index 0000000..c4bcc2e
--- /dev/null
@@ -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<OptionInfo*>(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<OptionInfo*>(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<OptionInfo*>(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<OptionInfo*>(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<OptionInfo*>(pointer);
+  return static_cast<jboolean>(current->setByUser);
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, static_cast<jboolean>(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<BigInteger>
+ */
+template <typename T>
+jobject getNumberInfoFromInteger(JNIEnv* env,
+                                 const _jobject* optionInfo,
+                                 jclass numberInfoClass,
+                                 jmethodID methodId,
+                                 const OptionInfo::NumberInfo<T>& info)
+{
+  jobject defaultValue = getBigIntegerObject<T>(env, info.defaultValue);
+  jobject currentValue = getBigIntegerObject<T>(env, info.currentValue);
+  jobject minimum = nullptr;
+  if (info.minimum)
+  {
+    minimum = getBigIntegerObject<T>(env, *info.minimum);
+  }
+  jobject maximum = nullptr;
+  if (info.maximum)
+  {
+    maximum = getBigIntegerObject<T>(env, *info.maximum);
+  }
+  jobject ret = env->NewObject(numberInfoClass,
+                               methodId,
+                               optionInfo,
+                               defaultValue,
+                               currentValue,
+                               minimum,
+                               maximum);
+
+  return ret;
+}
+
+template <typename T>
+jobject getNumberInfoFromInteger(JNIEnv* env,
+                                 const _jobject* optionInfo,
+                                 jclass numberInfoClass,
+                                 jmethodID methodId,
+                                 const OptionInfo::NumberInfo<int64_t>& info);
+
+template <typename T>
+jobject getNumberInfoFromInteger(JNIEnv* env,
+                                 const _jobject* optionInfo,
+                                 jclass numberInfoClass,
+                                 jmethodID methodId,
+                                 const OptionInfo::NumberInfo<uint64_t>& 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<OptionInfo*>(pointer);
+  std::variant<OptionInfo::VoidInfo,
+               OptionInfo::ValueInfo<bool>,
+               OptionInfo::ValueInfo<std::string>,
+               OptionInfo::NumberInfo<int64_t>,
+               OptionInfo::NumberInfo<uint64_t>,
+               OptionInfo::NumberInfo<double>,
+               OptionInfo::ModeInfo>
+      v = current->valueInfo;
+
+  if (std::holds_alternative<OptionInfo::VoidInfo>(v))
+  {
+    jclass voidInfoClass = env->FindClass("cvc5/OptionInfo$VoidInfo");
+    jmethodID methodId =
+        env->GetMethodID(voidInfoClass, "<init>", "(Lcvc5/OptionInfo;)V");
+    jobject ret = env->NewObject(voidInfoClass, methodId, optionInfo);
+    return ret;
+  }
+
+  if (std::holds_alternative<OptionInfo::ValueInfo<bool>>(v)
+      || std::holds_alternative<OptionInfo::ValueInfo<std::string>>(v))
+  {
+    jclass valueInfoClass = env->FindClass("cvc5/OptionInfo$ValueInfo");
+    jmethodID methodId = env->GetMethodID(
+        valueInfoClass,
+        "<init>",
+        "(Lcvc5/OptionInfo;Ljava/lang/Object;Ljava/lang/Object;)V");
+
+    if (std::holds_alternative<OptionInfo::ValueInfo<bool>>(v))
+    {
+      auto info = std::get<OptionInfo::ValueInfo<bool>>(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<OptionInfo::ValueInfo<std::string>>(v))
+    {
+      auto info = std::get<OptionInfo::ValueInfo<std::string>>(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<OptionInfo::NumberInfo<int64_t>>(v)
+      || std::holds_alternative<OptionInfo::NumberInfo<uint64_t>>(v)
+      || std::holds_alternative<OptionInfo::NumberInfo<double>>(v))
+  {
+    jclass numberInfoClass = env->FindClass("cvc5/OptionInfo$NumberInfo");
+    jmethodID methodId =
+        env->GetMethodID(numberInfoClass,
+                         "<init>",
+                         "(Lcvc5/OptionInfo;Ljava/lang/Object;Ljava/lang/"
+                         "Object;Ljava/lang/Object;Ljava/lang/Object;)V");
+
+    if (std::holds_alternative<OptionInfo::NumberInfo<int64_t>>(v))
+    {
+      auto info = std::get<OptionInfo::NumberInfo<int64_t>>(v);
+      return getNumberInfoFromInteger(
+          env, optionInfo, numberInfoClass, methodId, info);
+    }
+
+    if (std::holds_alternative<OptionInfo::NumberInfo<uint64_t>>(v))
+    {
+      auto info = std::get<OptionInfo::NumberInfo<uint64_t>>(v);
+      return getNumberInfoFromInteger(
+          env, optionInfo, numberInfoClass, methodId, info);
+    }
+
+    if (std::holds_alternative<OptionInfo::NumberInfo<double>>(v))
+    {
+      auto info = std::get<OptionInfo::NumberInfo<double>>(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<OptionInfo::ModeInfo>(v))
+  {
+    jclass modeInfoClass = env->FindClass("cvc5/OptionInfo$ModeInfo");
+    jmethodID methodId =
+        env->GetMethodID(modeInfoClass,
+                         "<init>",
+                         "(Lcvc5/OptionInfo;Ljava/lang/String;Ljava/lang/"
+                         "String;[Ljava/lang/String;)V");
+
+    auto info = std::get<OptionInfo::ModeInfo>(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<OptionInfo*>(pointer);
+  return static_cast<jboolean>(current->boolValue());
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, static_cast<jboolean>(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<OptionInfo*>(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<OptionInfo*>(pointer);
+  std::int64_t value = current->intValue();
+  jobject ret = getBigIntegerObject<std::int64_t>(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<OptionInfo*>(pointer);
+  double ret = current->doubleValue();
+  return static_cast<jdouble>(ret);
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, static_cast<jdouble>(0.0));
+}
index 53c050c96cec8d74d13ef15ee952018cf16148e8..cdbb48db05e28fe8c197b37380a57be7e914ca8a 100644 (file)
@@ -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<Solver*>(pointer);
+  std::vector<std::string> 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<Solver*>(pointer);
+  std::string cOption(env->GetStringUTFChars(jOption, nullptr));
+  OptionInfo* ret = new OptionInfo(solver->getOptionInfo(cOption));
+  return reinterpret_cast<jlong>(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<Solver*>(pointer);
+  DriverOptions* ret = new DriverOptions(solver->getDriverOptions());
+  return reinterpret_cast<jlong>(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<Solver*>(pointer);
+  std::map<Term, Term> map = solver->getDifficulty();
+  // HashMap hashMap = new HashMap();
+  jclass hashMapClass = env->FindClass("Ljava/util/HashMap;");
+  jmethodID constructor = env->GetMethodID(hashMapClass, "<init>", "()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, "<init>", "(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<jlong>(termKey));
+    jobject value = env->NewObject(
+        longClass, longConstructor, reinterpret_cast<jlong>(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<Solver*>(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<Solver*>(pointer);
+  Sort* sort = reinterpret_cast<Sort*>(sortPointer);
+  std::vector<Term> terms = solver->getModelDomainElements(*sort);
+  jlongArray ret = getPointersFromObjects<Term>(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<Solver*>(pointer);
+  Term* term = reinterpret_cast<Term*>(termPointer);
+  solver->addSygusAssume(*term);
+  CVC5_JAVA_API_TRY_CATCH_END(env);
+}
+
 /*
  * Class:     cvc5_Solver
  * Method:    addSygusInvConstraint
index 6f9d8206db5ea5b01e6e2a800e9e977da71634e6..971be58cc08376c94ae3e92e11deec654b8b42ef 100644 (file)
@@ -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<Executable> 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<BigInteger> numInfo =
+          (OptionInfo.NumberInfo<BigInteger>) 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<Double> ni = (OptionInfo.NumberInfo<Double>) 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<Term[]> 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<Term, Term> dmap = d_solver.getDifficulty();
+    // difficulty should map assertions to integer values
+    for (Map.Entry<Term, Term> 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();