Clingo
Loading...
Searching...
No Matches
solve.hh
1#pragma once
2
3#include <clingo/base.hh>
4#include <clingo/core.hh>
5#include <clingo/stats.hh>
6
7#include <clingo/solve.h>
8
9namespace Clingo {
10
14
17 public:
21 explicit SolveResult(clingo_solve_result_bitset_t res) : res_{res} {}
22
26 [[nodiscard]] auto satisfiable() const -> bool { return (res_ & clingo_solve_result_satisfiable) != 0; }
27
31 [[nodiscard]] auto unsatisfiable() const -> bool { return (res_ & clingo_solve_result_unsatisfiable) != 0; }
32
36 [[nodiscard]] auto unknown() const -> bool {
38 }
39
43 [[nodiscard]] auto exhausted() const -> bool { return (res_ & clingo_solve_result_exhausted) != 0; }
44
48 [[nodiscard]] auto interrupted() const -> bool { return (res_ & clingo_solve_result_interrupted) != 0; }
49
53 [[nodiscard]] auto to_string() const -> std::string_view {
54 if (satisfiable()) {
55 return "SAT";
56 }
57 if (unsatisfiable()) {
58 return "UNSAT";
59 }
60 return "UNKNOWN";
61 }
62
63 private:
65};
66
69 public:
73 explicit SolveControl(clingo_solve_control_t *ctl) : ctl_{ctl} {}
74
78 [[nodiscard]] auto base() const -> Base { return Base{Detail::call<clingo_solve_control_base>(ctl_)}; }
79
83 void add_clause(ProgramLiteralSpan lits) const {
84 Detail::handle_error(clingo_solve_control_add_clause(ctl_, lits.data(), lits.size()));
85 }
86
93 void add_nogood(ProgramLiteralSpan lits) const {
94 add_clause(Detail::transform(lits, [](auto const &lit) { return -lit; }));
95 }
96
97 private:
99};
100
108
119
122 public:
128 explicit ConstModel(clingo_model_t const *mdl) : mdl_{mdl} {}
129
134 friend auto c_cast(ConstModel const &x) -> clingo_model_t const * { return x.mdl_; }
135
140 [[nodiscard]] auto symbols(ShowFlags flags = ShowFlags::shown) const -> SymbolVector {
141 auto res = SymbolVector{};
142 Detail::handle_error(clingo_model_symbols(mdl_, static_cast<clingo_show_type_bitset_t>(flags), &sym_cb_, &res));
143 return res;
144 }
145
150 [[nodiscard]] auto contains(Symbol const &atom) const -> bool {
151 return Detail::call<clingo_model_contains>(mdl_, c_cast(atom));
152 }
153
157 [[nodiscard]] auto type() const -> ModelType {
158 return static_cast<ModelType>(Detail::call<clingo_model_type>(mdl_));
159 }
160
164 [[nodiscard]] auto number() const -> uint64_t { return Detail::call<clingo_model_number>(mdl_); }
165
170 [[nodiscard]] auto is_true(ProgramLiteral lit) const -> bool {
171 return Detail::call<clingo_model_is_true>(mdl_, lit);
172 }
173
182 [[nodiscard]] auto is_consequence(ProgramLiteral lit) const -> std::optional<bool> {
183 auto res = Detail::call<clingo_model_is_consequence>(mdl_, lit);
184 if (res != clingo_consequence_unknown) {
185 return res == clingo_consequence_true;
186 }
187 return std::nullopt;
188 }
189
195 [[nodiscard]] auto cost() const -> SumSpan {
196 int64_t const *costs = nullptr;
197 size_t size = 0;
198 Detail::handle_error(clingo_model_cost(mdl_, &costs, &size));
199 return {costs, size};
200 }
201
205 [[nodiscard]] auto priorities() const -> WeightSpan {
206 clingo_weight_t const *prios = nullptr;
207 size_t size = 0;
208 Detail::handle_error(clingo_model_priority(mdl_, &prios, &size));
209 return {prios, size};
210 }
211
218 [[nodiscard]] auto optimality_proven() const -> bool { return Detail::call<clingo_model_optimality_proven>(mdl_); }
219
223 [[nodiscard]] auto thread_id() const -> ProgramId { return Detail::call<clingo_model_thread_id>(mdl_); }
224
228 [[nodiscard]] auto to_string() const -> std::string {
229 auto res = std::string{};
230 auto comma = false;
231 for (auto const &sym : symbols(ShowFlags::shown)) {
232 res += comma ? ", " : "";
233 res += sym.to_string();
234 comma = true;
235 }
236 return res;
237 }
238
239 private:
240 static auto sym_cb_(clingo_symbol_t const *symbols, size_t size, void *data) -> bool {
241 auto *res = static_cast<SymbolVector *>(data);
242 CLINGO_TRY {
243 // NOLINTNEXTLINE
244 res->insert(res->end(), cpp_cast(symbols), cpp_cast(symbols) + size);
245 }
246 CLINGO_CATCH;
247 }
248
249 clingo_model_t const *mdl_;
250};
251
256class Model : public ConstModel {
257 public:
261 explicit Model(clingo_model_t *mdl) : ConstModel{mdl} {}
262
267 friend auto c_cast(Model const &x) -> clingo_model_t * { return x.mdl_(); }
268
272 [[nodiscard]] auto control() const -> SolveControl {
273 return SolveControl{Detail::call<clingo_model_control>(mdl_())};
274 }
275
280 Detail::handle_error(clingo_model_extend(mdl_(), c_cast(symbols.data()), symbols.size()));
281 }
282
283 private:
284 [[nodiscard]] auto mdl_() const -> clingo_model_t * {
285 // NOLINTNEXTLINE
286 return const_cast<clingo_model_t *>(c_cast(*static_cast<ConstModel const *>(this)));
287 }
288};
289
292 public:
294 SolveEventHandler() = default;
295
299 auto operator=(SolveEventHandler &&other) -> SolveEventHandler & = delete;
300
302 virtual ~SolveEventHandler() = default;
303
308 auto model(Model model) -> bool { return do_model(model); }
309
313 void unsat(SumSpan lower_bound) { do_unsat(lower_bound); }
314
319 void stats(Stats step, Stats accu) { do_stats(step, accu); }
320
327 void finish(SolveResult result) noexcept { do_finish(result); }
328
329 private:
330 virtual auto do_model([[maybe_unused]] Model model) -> bool { return true; }
331 virtual void do_unsat([[maybe_unused]] SumSpan lower_bound) {}
332 virtual void do_stats([[maybe_unused]] Stats step, [[maybe_unused]] Stats accu) {}
333 virtual void do_finish([[maybe_unused]] SolveResult result) noexcept {}
334};
335
338 public:
340 struct sentinel {};
342 class iterator {
343 public:
345 using iterator_category = std::input_iterator_tag;
347 using difference_type = std::ptrdiff_t;
354
358 iterator() = default;
359
361 auto operator*() const -> reference {
362 return mdl_.value(); // NOLINT
363 }
364
366 auto operator->() const -> pointer {
367 return &mdl_.value(); // NOLINT
368 }
369
371 auto operator++() -> iterator & {
372 hnd_->resume();
373 mdl_ = hnd_->model();
374 return *this;
375 }
376
380 auto operator++(int) -> iterator {
381 iterator tmp = *this;
382 ++(*this);
383 return tmp;
384 }
385
393 friend auto operator==(const iterator &a, const iterator &b) -> bool { return a.hnd_ == b.hnd_; }
394
400 friend auto operator==(iterator const &a, [[maybe_unused]] sentinel const &b) -> bool {
401 return !a.mdl_.has_value();
402 }
403
404 private:
405 friend class SolveHandle;
406
407 explicit iterator(SolveHandle &hnd) : hnd_{&hnd} { operator++(); }
408
409 SolveHandle *hnd_ = nullptr;
410 mutable std::optional<value_type> mdl_;
411 };
420
426 explicit SolveHandle(clingo_solve_handle_t *hnd) : hnd_{hnd} {}
427
431 friend auto c_cast(SolveHandle const &x) -> clingo_solve_handle_t * { return x.hnd_.get(); }
432
439 [[nodiscard]] auto get() const -> SolveResult {
440 return SolveResult{Detail::call<clingo_solve_handle_get>(hnd_.get())};
441 }
442
446 void cancel() { Detail::handle_error(clingo_solve_handle_cancel(hnd_.get())); }
447
454 void close() { Detail::handle_error(clingo_solve_handle_close(hnd_.release())); }
455
460 void resume() { Detail::handle_error(clingo_solve_handle_resume(hnd_.get())); }
461
469 [[nodiscard]] auto model() -> std::optional<ConstModel> {
470 clingo_model_t const *mdl = Detail::call<clingo_solve_handle_model>(hnd_.get());
471 return mdl != nullptr ? std::make_optional<ConstModel>(mdl) : std::nullopt;
472 }
473
480 [[nodiscard]] auto last() const -> std::optional<ConstModel> {
481 clingo_model_t const *mdl = Detail::call<clingo_solve_handle_last>(hnd_.get());
482 return mdl != nullptr ? std::make_optional<ConstModel>(mdl) : std::nullopt;
483 }
484
492 [[nodiscard]] auto core() const -> ProgramLiteralSpan {
493 auto const *lits = static_cast<clingo_literal_t *>(nullptr);
494 auto size = size_t{0};
495 Detail::handle_error(clingo_solve_handle_core(hnd_.get(), &lits, &size));
496 return {lits, size};
497 }
498
510 [[nodiscard]] auto wait(std::optional<double> timeout) -> bool {
511 return Detail::call<clingo_solve_handle_wait>(hnd_.get(), timeout ? *timeout : -1);
512 }
513
515 [[nodiscard]] auto begin() -> iterator { return iterator{*this}; }
517 [[nodiscard]] auto end() -> sentinel {
518 static_cast<void>(this);
519 return sentinel{};
520 }
521
522 private:
523 friend class Control;
524
525 struct Free {
526 Free() {
527 // NOTE: We assume that solve is only called during normal
528 // operation - not during exception handling.
529 assert(std::uncaught_exceptions() == 0);
530 }
531 void operator()(clingo_solve_handle_t *hnd) const noexcept(false) {
532 try {
533 // NOTE: currently the solve handle calls cancel and then
534 // deletes clasp's underlying solve handle. I am not sure
535 // whether this can actually throw or not.
536 Detail::handle_error(clingo_solve_handle_close(hnd));
537 } catch (...) {
538 if (std::uncaught_exceptions() == 1) {
539 throw;
540 }
541 }
542 }
543 };
544
545 std::unique_ptr<clingo_solve_handle_t, Free> hnd_;
546};
547static_assert(std::input_iterator<SolveHandle::iterator>);
548static_assert(std::sentinel_for<SolveHandle::sentinel, SolveHandle::iterator>);
549
551
552namespace Detail {
553
554static constexpr clingo_solve_event_handler_t c_solve_event_handler{
555 [](clingo_model_t *model, void *data, bool *goon) -> bool {
556 CLINGO_TRY {
557 auto *hnd = static_cast<SolveEventHandler *>(data);
558 assert(hnd != nullptr);
559 auto mdl = Model{model};
560 *goon = hnd->model(mdl);
561 return true;
562 }
563 CLINGO_CATCH;
564 },
565 [](int64_t const *values, size_t size, void *data) -> bool {
566 CLINGO_TRY {
567 auto *hnd = static_cast<SolveEventHandler *>(data);
568 assert(hnd != nullptr);
569 hnd->unsat({values, size});
570 }
571 CLINGO_CATCH;
572 },
573 [](clingo_stats_t *stats, void *data) -> bool {
574 CLINGO_TRY {
575 auto *hnd = static_cast<SolveEventHandler *>(data);
576 assert(hnd != nullptr);
577 std::string_view user_step = "user_step";
578 std::string_view user_accu = "user_accu";
579 uint64_t root = Detail::call<clingo_stats_root>(stats);
580 uint64_t step = Detail::call<clingo_stats_map_add_subkey>(stats, root, user_step.data(), user_step.size(),
582 uint64_t accu = Detail::call<clingo_stats_map_add_subkey>(stats, root, user_accu.data(), user_accu.size(),
584 hnd->stats(Stats{stats, step}, Stats{stats, accu});
585 }
586 CLINGO_CATCH;
587 },
588 [](clingo_solve_result_bitset_t result, void *data) -> void {
589 auto *hnd = static_cast<SolveEventHandler *>(data);
590 assert(hnd != nullptr);
591 hnd->finish(static_cast<SolveResult>(result));
592 },
593 nullptr,
594};
595
596} // namespace Detail
597
598} // namespace Clingo
A base that maps signatures to atom bases, and captures term and theory bases.
Definition base.hh:607
Class to provide an immutable view of a model.
Definition solve.hh:121
auto priorities() const -> WeightSpan
Get the priorities of the costs of a model.
Definition solve.hh:205
auto symbols(ShowFlags flags=ShowFlags::shown) const -> SymbolVector
Get the symbols of the model.
Definition solve.hh:140
auto optimality_proven() const -> bool
Check whether the model is proven to be optimal.
Definition solve.hh:218
auto is_true(ProgramLiteral lit) const -> bool
Check whether the given literal is true in the model.
Definition solve.hh:170
auto thread_id() const -> ProgramId
Get the thread id of the solver that found the model.
Definition solve.hh:223
auto number() const -> uint64_t
Get the running number of the model.
Definition solve.hh:164
friend auto c_cast(ConstModel const &x) -> clingo_model_t const *
Cast the model to its C representation.
Definition solve.hh:134
auto contains(Symbol const &atom) const -> bool
Check if the model contains a specific atom.
Definition solve.hh:150
auto cost() const -> SumSpan
Get the cost of the model.
Definition solve.hh:195
auto type() const -> ModelType
Get the type of the model.
Definition solve.hh:157
auto is_consequence(ProgramLiteral lit) const -> std::optional< bool >
Check whether the given literal is consequence of the model.
Definition solve.hh:182
ConstModel(clingo_model_t const *mdl)
Constructor from the underlying C representation.
Definition solve.hh:128
auto to_string() const -> std::string
Convert the model to a string representation.
Definition solve.hh:228
The main control class for grounding and solving logic programs.
Definition control.hh:228
Class to provide an mutable view of a model.
Definition solve.hh:256
auto control() const -> SolveControl
Get the associated solve control object.
Definition solve.hh:272
friend auto c_cast(Model const &x) -> clingo_model_t *
Cast the model to its C representation.
Definition solve.hh:267
void extend(SymbolSpan symbols) const
Extend the model with additional symbols.
Definition solve.hh:279
Model(clingo_model_t *mdl)
Constructor from the underlying C representation.
Definition solve.hh:261
Class to add clauses to a running search.
Definition solve.hh:68
auto base() const -> Base
Get base associated with the solve control.
Definition solve.hh:78
SolveControl(clingo_solve_control_t *ctl)
Constructor from the underlying C representation.
Definition solve.hh:73
void add_nogood(ProgramLiteralSpan lits) const
Add clause to the running search.
Definition solve.hh:93
void add_clause(ProgramLiteralSpan lits) const
Add clause to the running search.
Definition solve.hh:83
Interface to handle events during solving.
Definition solve.hh:291
SolveEventHandler(SolveEventHandler &&other)=delete
Disable copy and move operations.
void unsat(SumSpan lower_bound)
Callback to inspect lower bounds found during solving.
Definition solve.hh:313
void stats(Stats step, Stats accu)
Callback to update solving statistics.
Definition solve.hh:319
void finish(SolveResult result) noexcept
Callback to handle the end of solving.
Definition solve.hh:327
SolveEventHandler()=default
The default constructor.
auto model(Model model) -> bool
Callback to interact with the model found during solving.
Definition solve.hh:308
virtual ~SolveEventHandler()=default
The default destructor.
auto operator=(SolveEventHandler &&other) -> SolveEventHandler &=delete
Disable copy and move operations.
Iterator to iterate over models found during solving.
Definition solve.hh:342
auto operator++() -> iterator &
Increment the iterator to the next model.
Definition solve.hh:371
std::ptrdiff_t difference_type
The difference type.
Definition solve.hh:347
ConstModel & reference
The reference type.
Definition solve.hh:353
friend auto operator==(iterator const &a, sentinel const &b) -> bool
Check whether all models have been exhausted.
Definition solve.hh:400
std::input_iterator_tag iterator_category
The iterator category.
Definition solve.hh:345
ConstModel * pointer
The pointer type.
Definition solve.hh:351
friend auto operator==(const iterator &a, const iterator &b) -> bool
Compare iterators for equality.
Definition solve.hh:393
auto operator->() const -> pointer
Member access operator to get a pointer to the current model.
Definition solve.hh:366
ConstModel value_type
The value type, which are models.
Definition solve.hh:349
iterator()=default
The default constructor.
auto operator++(int) -> iterator
Postfix increment the iterator.
Definition solve.hh:380
auto operator*() const -> reference
Get a reference to the current model.
Definition solve.hh:361
Class to control a running search.
Definition solve.hh:337
void cancel()
Cancel the current search.
Definition solve.hh:446
auto begin() -> iterator
Get an iterator to iterate over models found during solving.
Definition solve.hh:515
auto end() -> sentinel
Get a sentinel to indicate that all models have been exhausted.
Definition solve.hh:517
auto model() -> std::optional< ConstModel >
Get the current model.
Definition solve.hh:469
void resume()
Resume the current search.
Definition solve.hh:460
auto get() const -> SolveResult
Get the solve result.
Definition solve.hh:439
auto core() const -> ProgramLiteralSpan
Get the unsatisfiable core.
Definition solve.hh:492
friend auto c_cast(SolveHandle const &x) -> clingo_solve_handle_t *
Cast the solve handle to its C representation.
Definition solve.hh:431
auto last() const -> std::optional< ConstModel >
Get the last model.
Definition solve.hh:480
SolveHandle(clingo_solve_handle_t *hnd)
Constructor from the underlying C representation.
Definition solve.hh:426
iterator::difference_type difference_type
The difference type.
Definition solve.hh:413
auto wait(std::optional< double > timeout) -> bool
Wait for the next model or solve result.
Definition solve.hh:510
void close()
Close the solve handle.
Definition solve.hh:454
Class to capture the result of solve calls.
Definition solve.hh:16
auto interrupted() const -> bool
Check if the search was interrupted.
Definition solve.hh:48
auto unknown() const -> bool
Check if the result is unknown.
Definition solve.hh:36
auto unsatisfiable() const -> bool
Check if the result is unsatisfiable.
Definition solve.hh:31
SolveResult(clingo_solve_result_bitset_t res)
Construct the solve result from its C representation.
Definition solve.hh:21
auto satisfiable() const -> bool
Check if the result is satisfiable.
Definition solve.hh:26
auto exhausted() const -> bool
Check if the search space was exhausted.
Definition solve.hh:43
auto to_string() const -> std::string_view
Convert the solve result to a string representation.
Definition solve.hh:53
Class modeling a mutable view on a statistics entry.
Definition stats.hh:106
Class modeling a symbol in Clingo.
Definition symbol.hh:68
int32_t clingo_literal_t
Signed integer type used for aspif and solver literals.
Definition core.h:73
int32_t clingo_weight_t
Signed integer type for weights in sum aggregates and minimize constraints.
Definition core.h:79
CLINGO_VISIBILITY_DEFAULT bool clingo_solve_control_add_clause(clingo_solve_control_t *control, clingo_literal_t const *clause, size_t size)
Add a clause that applies to the current solving step during model enumeration.
int clingo_model_type_t
Corresponding type to clingo_model_type_e.
Definition model.h:52
CLINGO_VISIBILITY_DEFAULT bool clingo_model_priority(clingo_model_t const *model, clingo_weight_t const **priorities, size_t *size)
Get the priorities of the costs.
CLINGO_VISIBILITY_DEFAULT bool clingo_model_symbols(clingo_model_t const *model, clingo_show_type_bitset_t show, clingo_symbol_callback_t callback, void *data)
Get the symbols of the selected types in the model.
CLINGO_VISIBILITY_DEFAULT bool clingo_model_cost(clingo_model_t const *model, int64_t const **costs, size_t *size)
Get the costs of a model.
struct clingo_model clingo_model_t
Object representing a model.
Definition model.h:43
struct clingo_solve_control clingo_solve_control_t
Object to add clauses during search.
Definition model.h:40
CLINGO_VISIBILITY_DEFAULT bool clingo_model_extend(clingo_model_t *model, clingo_symbol_t const *symbols, size_t size)
Add symbols to the model.
unsigned clingo_show_type_bitset_t
Corresponding type to clingo_show_type_e.
Definition model.h:63
@ clingo_model_type_stable_model
The model represents a stable model.
Definition model.h:47
@ clingo_model_type_cautious_consequences
The model represents a set of cautious consequences.
Definition model.h:49
@ clingo_model_type_brave_consequences
The model represents a set of brave consequences.
Definition model.h:48
@ clingo_show_type_theory
Select symbols added by theory.
Definition model.h:59
@ clingo_show_type_terms
Select all terms.
Definition model.h:58
@ clingo_show_type_shown
Select shown atoms and terms.
Definition model.h:56
@ clingo_show_type_atoms
Select all atoms.
Definition model.h:57
@ clingo_consequence_true
The literal is a consequence.
Definition model.h:68
@ clingo_consequence_unknown
The literal might or might not be a consequence.
Definition model.h:69
struct clingo_solve_handle clingo_solve_handle_t
Search handle to a solve call.
Definition solve.h:112
CLINGO_VISIBILITY_DEFAULT bool clingo_solve_handle_cancel(clingo_solve_handle_t *handle)
Stop the running search and block until done.
CLINGO_VISIBILITY_DEFAULT bool clingo_solve_handle_close(clingo_solve_handle_t *handle)
Stops the running search and releases the handle.
unsigned clingo_solve_result_bitset_t
Corresponding type to clingo_solve_result_e.
Definition solve.h:61
CLINGO_VISIBILITY_DEFAULT bool clingo_solve_handle_resume(clingo_solve_handle_t *handle)
Discards the last model and starts the search for the next one.
CLINGO_VISIBILITY_DEFAULT bool clingo_solve_handle_core(clingo_solve_handle_t *handle, clingo_literal_t const **literals, size_t *size)
When a problem is unsatisfiable, get a subset of the assumptions that made the problem unsatisfiable.
@ clingo_solve_result_satisfiable
The last solve call found a solution.
Definition solve.h:55
@ clingo_solve_result_interrupted
The last solve call was interrupted.
Definition solve.h:58
@ clingo_solve_result_exhausted
The last solve call completely exhausted the search space.
Definition solve.h:57
@ clingo_solve_result_unsatisfiable
The last solve call did not find a solution.
Definition solve.h:56
struct clingo_statistic clingo_stats_t
Handle for the solver stats.
Definition stats.h:59
@ clingo_stats_type_map
the entry is a map
Definition stats.h:53
uint64_t clingo_symbol_t
Type to represent a symbol.
Definition symbol.h:51
SolveResult
The solve result.
Definition solver.hh:304
@ model
The model represents a stable model.
@ symbols
Whether to write symbols in a structured format.
@ accu
Indicate accumulated profiling data.
@ step
Indicate per step profiling data.
std::span< Sum const > SumSpan
A span of sums.
Definition core.hh:420
clingo_literal_t ProgramLiteral
A program literal.
Definition core.hh:392
clingo_id_t ProgramId
A program id used for various kinds of indices.
Definition core.hh:382
std::span< ProgramLiteral const > ProgramLiteralSpan
A span of program literals.
Definition core.hh:394
std::span< clingo_weight_t const > WeightSpan
A span of weights.
Definition core.hh:410
@ none
The empty set of flags.
Definition propagate.hh:38
ShowFlags
Enumeration of bit flags to select symbols in models.
Definition solve.hh:110
ModelType
Enumeration of the model types.
Definition solve.hh:102
@ atoms
Select all atoms.
@ shown
Select shown atoms and terms.
@ terms
Select all terms.
@ theory
Select symbols added by theory.
@ cautious_consequences
The model represents a set of cautious consequences.
@ stable_model
The model represents a stable model.
@ brave_consequences
The model represents a set of brave consequences.
std::vector< Symbol > SymbolVector
A vector of symbols.
Definition symbol.hh:42
std::span< Symbol const > SymbolSpan
A span of symbols, which is a view on a contiguous sequence of symbols.
Definition symbol.hh:38
auto cpp_cast(clingo_symbol_t const *sym) -> Symbol const *
Cast a C symbol to its C++ representation.
Definition symbol.hh:52
#define CLINGO_ENABLE_BITSET_ENUM(E,...)
Opt-in macro for enabling bit operations for a given enum type.
Definition enum.hh:18
Sentinel indicating that models have been exhausted.
Definition solve.hh:340
The solve event handler interface.
Definition solve.h:74