potassco / clasp

⚙️ A conflict-driven nogood learning answer set solver

Home Page:https://potassco.org/clasp/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Exit code has ALLOPT bit set when bad alloc is thrown

rkaminsk opened this issue · comments

This was first reported in potassco/guide#19, where the std::bad_alloc was thrown in a propagator.

When there is a std::bad_alloc exception when enumerating models with --opt-mode=optN, then the OPTALL bit is set in the exit code. To test this with clasp, I did the following experiment:

diff --git a/src/minimize_constraint.cpp b/src/minimize_constraint.cpp
index d4e3a56..6d8aa3c 100644
--- a/src/minimize_constraint.cpp
+++ b/src/minimize_constraint.cpp
@@ -391,6 +391,7 @@ void DefaultMinimize::reason(Solver& s, Literal p, LitVec& lits) {
                x = shared_->lits[u.index()].first;
                lits.push_back(x);
        }
+       throw std::bad_alloc();
 }

And then run with the following small program:

$ echo "#minimize{ X : p(X) }. 3 { p(1..5) }. 3 { p(3..7) }. 3 { p(5..10) }."  \
  | gringo \
  |  ./bin/clasp 0 --opt-mode=optN \
  ; echo $?

clasp version 3.3.3
Reading from stdin
Solving...
Answer: 1
p(6) p(7) p(9) p(3) p(1) p(2)
Optimization: 28
Answer: 2
p(6) p(7) p(8) p(3) p(1) p(2)
Optimization: 27
*** ERROR: (clasp): std::bad_alloc
SATISFIABLE

INTERRUPTED  : 1
Models       : 2+
  Optimum    : unknown
Optimization : 27
Calls        : 1
Time         : 0.001s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.001s
43

Because exit code 43 corresponds to 101011, we have the bits INT, SAT, and ALLOPT set. The ALLOPT bit should not be set.

This is not a bug but simply a misinterpretation of clasp's exit codes. That is, clasp actually does not use the exit code encoding proposed in https://www.mat.unical.it/aspcomp2013/files/aspoutput.txt.
In particular, it has no concept of an ALLOPT bit. Instead, clasp uses a combination of the standard SAT competition codes together with some additional information regarding errors.
The codes are as follows:

enum ExitCode {
	E_UNKNOWN   = 0,  /*!< Satisfiablity of problem not knwon; search not started.    */
	E_INTERRUPT = 1,  /*!< Run was interrupted.                                       */
	E_SAT       = 10, /*!< At least one model was found.                              */
	E_EXHAUST   = 20, /*!< Search-space was completely examined.                      */
	E_MEMORY    = 33, /*!< Run was interrupted by out of memory exception.            */
	E_ERROR     = 65, /*!< Run was interrupted by internal error.                     */
	E_NO_RUN    = 128 /*!< Search not started because of syntax or command line error.*/
};

Hence, 43 is simply E_SAT + E_MEMORY - which is exactly what we we know about the program at the point of the exception.
Note that the meaning of 30 (i.e. E_SAT + E_EXHAUST) depends on the selected reasoning mode. E.g. for simple optimization it means optimum found. However, for optN it means all optimal models have been enumerated.

Okay. To be honest, I find those exit codes a bit scary. Let's keep it like it is but never do something like this again. 😄

Thank you, that is a perfectly nice documentation for the guide. 👍