@@ -688,6 +688,10 @@ void FRAIGSolver<SATSolverT>::verifyCandidates() {
688688 LLVM_DEBUG (llvm::dbgs () << " FRAIG: Starting SAT verification with "
689689 << equivClasses.size () << " equivalence classes\n " );
690690
691+ // Check if user wants to dump all SAT queries
692+ const char *dumpDir = std::getenv (" FRAIG_DUMP_SAT" );
693+ bool dumpAll = (dumpDir != nullptr );
694+
691695 // Global solver with bookmark/rollback (ABC-style):
692696 // - Pre-allocate variables for all values so they persist across rollbacks
693697 // - Learned clauses accumulate across equivalence classes (knowledge sharing)
@@ -729,6 +733,20 @@ void FRAIGSolver<SATSolverT>::verifyCandidates() {
729733
730734 // Check 1: Can rep=1 and target=0?
731735 stats.numSATCalls ++;
736+
737+ // Optionally dump SAT query for debugging
738+ if (dumpAll) {
739+ std::string filename = std::string (dumpDir) + " /sat_query_" +
740+ std::to_string (stats.numSATCalls ) + " _check1.cnf" ;
741+ std::error_code EC;
742+ llvm::raw_fd_ostream out (filename, EC);
743+ if (!EC) {
744+ solver.dumpDIMACS (out, {repVar, -targetLit});
745+ LLVM_DEBUG (llvm::dbgs ()
746+ << " FRAIG: Dumped SAT query to " << filename << " \n " );
747+ }
748+ }
749+
732750 solver.assume (repVar);
733751 solver.assume (-targetLit);
734752 auto result1 = solver.solve (conflictLimit);
@@ -749,6 +767,20 @@ void FRAIGSolver<SATSolverT>::verifyCandidates() {
749767
750768 // Check 2: Can rep=0 and target=1?
751769 stats.numSATCalls ++;
770+
771+ // Optionally dump SAT query for debugging
772+ if (dumpAll) {
773+ std::string filename = std::string (dumpDir) + " /sat_query_" +
774+ std::to_string (stats.numSATCalls ) + " _check2.cnf" ;
775+ std::error_code EC;
776+ llvm::raw_fd_ostream out (filename, EC);
777+ if (!EC) {
778+ solver.dumpDIMACS (out, {-repVar, targetLit});
779+ LLVM_DEBUG (llvm::dbgs ()
780+ << " FRAIG: Dumped SAT query to " << filename << " \n " );
781+ }
782+ }
783+
752784 solver.assume (-repVar);
753785 solver.assume (targetLit);
754786 auto result2 = solver.solve (conflictLimit);
@@ -940,6 +972,7 @@ class CadicalSATSolver : public IncrementalSATSolverBase<CadicalSATSolver> {
940972 LLVM_DEBUG (llvm::dbgs () << " Assuming: " << lit << " \n " );
941973 solver->assume (lit);
942974 testSolver.assume (lit);
975+ currentAssumptions.push_back (lit);
943976 }
944977
945978 [[nodiscard]] Result solve (int64_t confLimit = -1 ) {
@@ -979,8 +1012,38 @@ class CadicalSATSolver : public IncrementalSATSolverBase<CadicalSATSolver> {
9791012 : (miniSatResult == MiniSATSolver::kUNSAT ? " UNSAT"
9801013 : " UNKNOWN" ))
9811014 << " \n " ;
1015+
1016+ // Dump DIMACS reproducer for debugging
1017+ static int mismatchCount = 0 ;
1018+ std::string filename =
1019+ " /tmp/cadical_mismatch_" + std::to_string (++mismatchCount) + " .cnf" ;
1020+ std::error_code EC;
1021+ llvm::raw_fd_ostream out (filename, EC);
1022+ if (!EC) {
1023+ dumpDIMACS (out, currentAssumptions);
1024+ llvm::errs () << " Dumped reproducer to " << filename << " \n " ;
1025+ } else {
1026+ llvm::errs () << " Failed to dump reproducer: " << EC.message () << " \n " ;
1027+ }
1028+
1029+ // Also dump MiniSAT's view
1030+ std::string miniFilename =
1031+ " /tmp/minisat_mismatch_" + std::to_string (mismatchCount) + " .cnf" ;
1032+ llvm::raw_fd_ostream miniOut (miniFilename, EC);
1033+ if (!EC) {
1034+ // Convert assumptions to proper format for dumpDIMACS
1035+ llvm::SmallVector<int > extAssumptions;
1036+ for (int lit : currentAssumptions) {
1037+ extAssumptions.push_back (lit);
1038+ }
1039+ testSolver.dumpDIMACS (miniOut, extAssumptions);
1040+ llvm::errs () << " Dumped MiniSAT view to " << miniFilename << " \n " ;
1041+ }
9821042 }
9831043
1044+ // Clear assumptions for next solve
1045+ currentAssumptions.clear ();
1046+
9841047 return cadicalResult;
9851048 }
9861049
@@ -1046,13 +1109,46 @@ class CadicalSATSolver : public IncrementalSATSolverBase<CadicalSATSolver> {
10461109
10471110 [[nodiscard]] bool hasBookmark () const { return hasBookmark_; }
10481111
1112+ // / Export current formula in DIMACS CNF format for debugging.
1113+ void dumpDIMACS (llvm::raw_ostream &os,
1114+ llvm::ArrayRef<int > assumptions = {}) const {
1115+ // Count total clauses
1116+ size_t totalClauses = clauses.size () + assumptions.size ();
1117+
1118+ // DIMACS header (need to track maxVar)
1119+ int maxVar = 0 ;
1120+ for (const auto &clause : clauses) {
1121+ for (int lit : clause) {
1122+ maxVar = std::max (maxVar, std::abs (lit));
1123+ }
1124+ }
1125+ for (int lit : assumptions) {
1126+ maxVar = std::max (maxVar, std::abs (lit));
1127+ }
1128+
1129+ os << " p cnf " << maxVar << " " << totalClauses << " \n " ;
1130+
1131+ // All clauses
1132+ for (const auto &clause : clauses) {
1133+ for (int lit : clause)
1134+ os << lit << " " ;
1135+ os << " 0\n " ;
1136+ }
1137+
1138+ // Assumptions as unit clauses
1139+ for (int lit : assumptions) {
1140+ os << lit << " 0\n " ;
1141+ }
1142+ }
1143+
10491144private:
10501145 CaDiCaL::Solver *solver;
10511146 bool hasBookmark_ = false ;
10521147 llvm::SmallVector<llvm::SmallVector<int , 4 >, 0 > clauses; // All clauses added
10531148 llvm::SmallVector<llvm::SmallVector<int , 4 >, 0 >
10541149 bookmarkedClauses; // Clauses at bookmark
10551150 llvm::SmallVector<int , 4 > currentClause; // Current clause being built
1151+ llvm::SmallVector<int , 4 > currentAssumptions; // Current assumptions
10561152
10571153 MiniSATSolver testSolver;
10581154};
0 commit comments