Skip to content

Commit ac58131

Browse files
Implement context-based solver on top of prop_conv_solvert
Also allows using raw assumptions within contexts (as required by minimization and refinement algorithms).
1 parent bd5970c commit ac58131

File tree

2 files changed

+86
-14
lines changed

2 files changed

+86
-14
lines changed

src/solvers/prop/prop_conv_solver.cpp

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ bool prop_conv_solvert::set_equality_to_true(const equal_exprt &expr)
331331
return true;
332332
}
333333

334-
void prop_conv_solvert::set_to(const exprt &expr, bool value)
334+
void prop_conv_solvert::do_set_to(const exprt &expr, bool value)
335335
{
336336
PRECONDITION(expr.type().id() == ID_bool);
337337

@@ -346,7 +346,7 @@ void prop_conv_solvert::set_to(const exprt &expr, bool value)
346346
{
347347
if(expr.operands().size() == 1)
348348
{
349-
set_to(expr.op0(), !value);
349+
do_set_to(expr.op0(), !value);
350350
return;
351351
}
352352
}
@@ -359,7 +359,7 @@ void prop_conv_solvert::set_to(const exprt &expr, bool value)
359359
if(expr.id() == ID_and)
360360
{
361361
forall_operands(it, expr)
362-
set_to_true(*it);
362+
do_set_to(*it, true);
363363

364364
return;
365365
}
@@ -403,14 +403,14 @@ void prop_conv_solvert::set_to(const exprt &expr, bool value)
403403
{
404404
const implies_exprt &implies_expr = to_implies_expr(expr);
405405

406-
set_to_true(implies_expr.op0());
407-
set_to_false(implies_expr.op1());
406+
do_set_to(implies_expr.op0(), true);
407+
do_set_to(implies_expr.op1(), false);
408408
return;
409409
}
410410
else if(expr.id() == ID_or) // !(a || b) == (!a && !b)
411411
{
412412
forall_operands(it, expr)
413-
set_to_false(*it);
413+
do_set_to(*it, false);
414414
return;
415415
}
416416
}
@@ -493,3 +493,51 @@ std::size_t prop_conv_solvert::get_number_of_solver_calls() const
493493
{
494494
return prop.get_number_of_solver_calls();
495495
}
496+
497+
const char *prop_conv_solvert::context_prefix = "prop_conv::context$";
498+
499+
void prop_conv_solvert::set_to(const exprt &expr, bool value)
500+
{
501+
if(context_literals.empty())
502+
{
503+
// We are in the root context.
504+
do_set_to(expr, value);
505+
}
506+
else
507+
{
508+
// We have a child context. We add context_literal ==> expr to the formula.
509+
do_set_to(or_exprt(literal_exprt(!context_literals.back()), expr), value);
510+
}
511+
}
512+
513+
void prop_conv_solvert::set_assumptions(const bvt &assumptions)
514+
{
515+
bvt combined_assumptions;
516+
combined_assumptions.reserve(context_literals.size() + assumptions.size());
517+
combined_assumptions.insert(
518+
combined_assumptions.end(),
519+
context_literals.begin(),
520+
context_literals.end());
521+
combined_assumptions.insert(
522+
combined_assumptions.end(), assumptions.begin(), assumptions.end());
523+
prop.set_assumptions(combined_assumptions);
524+
}
525+
526+
void prop_conv_solvert::push_context()
527+
{
528+
// We create a new context literal.
529+
literalt context_literal = prop_conv_solvert::convert(symbol_exprt(
530+
context_prefix + std::to_string(context_literal_counter++), bool_typet()));
531+
532+
context_literals.push_back(context_literal);
533+
prop.set_assumptions(context_literals);
534+
}
535+
536+
void prop_conv_solvert::pop_context()
537+
{
538+
PRECONDITION(!context_literals.empty());
539+
540+
// We remove the last context literal from the stack.
541+
context_literals.pop_back();
542+
prop.set_assumptions(context_literals);
543+
}

src/solvers/prop/prop_conv_solver.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/message.h>
1717
#include <util/std_expr.h>
1818

19-
#include "decision_procedure_assumptions.h"
19+
#include "decision_procedure_contexts.h"
2020
#include "literal.h"
2121
#include "literal_expr.h"
2222
#include "prop.h"
2323
#include "solver_conflicts.h"
2424
#include "solver_resource_limits.h"
2525

26-
class prop_conv_solvert : public decision_procedure_assumptionst,
26+
class prop_conv_solvert : public decision_procedure_contextst,
2727
public solver_conflictst,
2828
public solver_resource_limitst
2929
{
@@ -36,7 +36,6 @@ class prop_conv_solvert : public decision_procedure_assumptionst,
3636
virtual ~prop_conv_solvert() = default;
3737

3838
// overloading from decision_proceduret
39-
void set_to(const exprt &expr, bool value) override;
4039
decision_proceduret::resultt dec_solve() override;
4140
void print_assignment(std::ostream &out) const override;
4241
std::string decision_procedure_text() const override
@@ -55,10 +54,7 @@ class prop_conv_solvert : public decision_procedure_assumptionst,
5554
{
5655
prop.set_frozen(a);
5756
}
58-
void set_assumptions(const bvt &_assumptions) override
59-
{
60-
prop.set_assumptions(_assumptions);
61-
}
57+
6258
void set_all_frozen() override
6359
{
6460
freeze_all = true;
@@ -69,6 +65,26 @@ class prop_conv_solvert : public decision_procedure_assumptionst,
6965
return prop.is_in_conflict(l);
7066
}
7167

68+
/// For a Boolean expression \p expr, add the constraint
69+
/// 'current_context => expr' if \p value is `true`,
70+
/// otherwise add 'current_context => not expr'
71+
void set_to(const exprt &expr, bool value) override;
72+
73+
/// Set \p assumptions within current context.
74+
/// These assumptions can be removed by passing empty \p assumptions.
75+
/// These assumptions will also be dropped in the course of any context
76+
/// operation (`push_context` or `pop_context`).
77+
void set_assumptions(const bvt &assumptions) override;
78+
79+
/// Push a new context on the stack
80+
/// This context becomes a child context nested in the current context.
81+
void push_context() override;
82+
83+
/// Pop the current context
84+
void pop_context() override;
85+
86+
static const char *context_prefix;
87+
7288
// get literal for expression, if available
7389
bool literal(const symbol_exprt &expr, literalt &literal) const;
7490

@@ -123,10 +139,18 @@ class prop_conv_solvert : public decision_procedure_assumptionst,
123139

124140
virtual void ignoring(const exprt &expr);
125141

126-
// deliberately protected now to protect lower-level API
142+
/// Actually adds the constraints to `prop`
143+
void do_set_to(const exprt &expr, bool value);
144+
127145
propt &prop;
128146

129147
messaget log;
148+
149+
/// Context literals used as assumptions
150+
bvt context_literals;
151+
152+
/// Unique context literal names
153+
std::size_t context_literal_counter = 0;
130154
};
131155

132156
#endif // CPROVER_SOLVERS_PROP_PROP_CONV_SOLVER_H

0 commit comments

Comments
 (0)