1212
1313#include < algorithm>
1414#include < expected>
15+ #include < numeric>
1516#include < optional>
1617#include < ranges>
1718
18- #include " common/exception.hh"
1919#include " common/logging.hh"
2020#include " solver.hh"
2121
2222#include " solver_context.hh"
2323
24- #include < numeric>
25-
26- namespace fabko ::compiler::sat {
27- namespace impl_details {
24+ namespace fabko ::compiler::sat::impl_details {
2825
2926namespace {
3027constexpr std::string SECTION = " sat_solver" ; // !< logging a section for the SAT solver
@@ -127,7 +124,7 @@ conflict_resolution_result resolve_conflict(Solver_Context& ctx, Clauses_Soa::so
127124 const auto & trail_assign_ctx = get<soa_assignment_ctx>(trail_node);
128125
129126 if (!trail_assign_ctx.is_decision () && trail_assign_ctx.decision_level_ == ctx.current_decision_level_ ) {
130- if (std::ranges::any_of (current_level_vars, [trail_var](const auto & ss ) { return get<soa_literal>(ss ).value () == trail_var; })) {
127+ if (std::ranges::any_of (current_level_vars, [trail_var](const auto & current_var ) { return get<soa_literal>(current_var ).value () == trail_var; })) {
131128 break ;
132129 }
133130 }
@@ -155,15 +152,18 @@ conflict_resolution_result resolve_conflict(Solver_Context& ctx, Clauses_Soa::so
155152
156153 // add literals from the propagation clause (except current trail literal)
157154 for (const auto [prop_lit, prop_varid] : propagation_vars) {
155+ const auto prop_node = ctx.vars_soa_ [prop_varid];
156+ const auto & prop_assign_ctx = get<soa_assignment_ctx>(prop_node);
157+
158158 if (prop_lit.value () == trail_lit.value ()
159159 || std::ranges::any_of (learned_clause, [&prop_lit](const auto & lit_map) { return prop_lit.value () == lit_map.first .value (); }))
160160 continue ;
161161
162162 learned_clause.emplace_back (prop_lit, prop_varid);
163- if (trail_assign_ctx .decision_level_ == ctx.current_decision_level_ ) {
164- current_level_vars.push_back (ctx. vars_soa_ [prop_varid] );
165- } else if (trail_assign_ctx .decision_level_ > backtrack_level) {
166- backtrack_level = trail_assign_ctx .decision_level_ ;
163+ if (prop_assign_ctx .decision_level_ == ctx.current_decision_level_ ) {
164+ current_level_vars.push_back (prop_node );
165+ } else if (prop_assign_ctx .decision_level_ > backtrack_level) {
166+ backtrack_level = prop_assign_ctx .decision_level_ ;
167167 }
168168 }
169169 }
@@ -305,7 +305,7 @@ bool make_decision(Solver_Context& ctx) {
305305 auto & [lit, assignment, assignment_context, meta] = s;
306306
307307 assignment_context.decision_level_ = ctx.current_decision_level_ ;
308- assignment = assignment::on; // always set at on by default. Off will be set by propagation (@incomplete : really ?)
308+ assignment = assignment::on;
309309
310310 log_debug (" make decision: level({}) :: {} -> {}" , ctx.current_decision_level_ , lit.value (), to_string (assignment));
311311 ctx.trail_ .push_back ((*var_highest_vsids).struct_id ());
@@ -314,9 +314,6 @@ bool make_decision(Solver_Context& ctx) {
314314}
315315
316316std::expected<solver::result, sat_error> solve_sat (Solver_Context& ctx, const Model& model) {
317- if (unit_propagation (ctx).has_value ())
318- return std::unexpected (sat_error::unsatisfiable);
319-
320317 solver::result solution;
321318 while (solution.literals .empty ()) {
322319 if (ctx.conflict_count_since_last_restart_ >= ctx.config_ .restart_threshold ) {
@@ -330,12 +327,16 @@ std::expected<solver::result, sat_error> solve_sat(Solver_Context& ctx, const Mo
330327 ctx.config_ .restart_threshold *= static_cast <int >(ctx.config_ .restart_multiplier );
331328 }
332329
333- const auto conflict = unit_propagation (ctx);
334- if (conflict.has_value ()) {
330+ if (const auto conflict = unit_propagation (ctx); conflict.has_value ()) {
335331 ++ctx.conflict_count_since_last_restart_ ;
336332 ++ctx.statistics_ .conflicts ;
337333 const auto & [learned_clause, backtrack_level] = resolve_conflict (ctx, ctx.clauses_soa_ [conflict.value ()]);
338334
335+ if (ctx.current_decision_level_ == 0 && backtrack_level == 0 ) {
336+ log_info (" Conflict found on level 0, unsatisfiable" );
337+ return std::unexpected (sat_error::unsatisfiable);
338+ }
339+
339340 if (learned_clause.is_empty ()) {
340341 log_info (" Conflict resolved into an empty clause, unsatisfiable" );
341342 return std::unexpected (sat_error::unsatisfiable);
@@ -367,5 +368,4 @@ std::expected<solver::result, sat_error> solve_sat(Solver_Context& ctx, const Mo
367368 return solution;
368369}
369370
370- } // namespace impl_details
371- } // namespace fabko::compiler::sat
371+ } // namespace fabko::compiler::sat::impl_details
0 commit comments