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:
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:
74
78 [[nodiscard]] auto base() const -> Base { return Base{Detail::call<clingo_solve_control_base>(ctl_)}; }
79
84 Detail::handle_error(clingo_solve_control_add_clause(ctl_, lits.data(), lits.size()));
85 }
86
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
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
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);
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
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:
262
267 friend auto c_cast(Model const &x) -> clingo_model_t * { return x.mdl_(); }
268
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
298
300 virtual ~SolveEventHandler() = default;
301
306 auto model(Model model) -> bool { return do_model(model); }
307
312
317 void stats(Stats step, Stats accu) { do_stats(step, accu); }
318
325 void finish(SolveResult result) noexcept { do_finish(result); }
326
327 private:
328 virtual auto do_model([[maybe_unused]] Model model) -> bool { return true; }
329 virtual void do_unsat([[maybe_unused]] SumSpan lower_bound) {}
330 virtual void do_stats([[maybe_unused]] Stats step, [[maybe_unused]] Stats accu) {}
331 virtual void do_finish([[maybe_unused]] SolveResult result) noexcept {}
332};
333
336 public:
338 struct sentinel {};
340 class iterator {
341 public:
343 using iterator_category = std::input_iterator_tag;
345 using difference_type = std::ptrdiff_t;
352
356 iterator() = default;
357
360 return mdl_.value(); // NOLINT
361 }
362
365 return &mdl_.value(); // NOLINT
366 }
367
369 auto operator++() -> iterator & {
370 hnd_->resume();
371 mdl_ = hnd_->model();
372 return *this;
373 }
374
378 auto operator++(int) -> iterator {
379 iterator tmp = *this;
380 ++(*this);
381 return tmp;
382 }
383
391 friend auto operator==(const iterator &a, const iterator &b) -> bool { return a.hnd_ == b.hnd_; }
392
398 friend auto operator==(iterator const &a, [[maybe_unused]] sentinel const &b) -> bool {
399 return !a.mdl_.has_value();
400 }
401
402 private:
403 friend class SolveHandle;
404
405 explicit iterator(SolveHandle &hnd) : hnd_{&hnd} { operator++(); }
406
407 SolveHandle *hnd_ = nullptr;
408 mutable std::optional<value_type> mdl_;
409 };
418
425
429 friend auto c_cast(SolveHandle const &x) -> clingo_solve_handle_t * { return x.hnd_.get(); }
430
438 return SolveResult{Detail::call<clingo_solve_handle_get>(hnd_.get())};
439 }
440
444 void cancel() { Detail::handle_error(clingo_solve_handle_cancel(hnd_.get())); }
445
452 void close() { Detail::handle_error(clingo_solve_handle_close(hnd_.release())); }
453
458 void resume() { Detail::handle_error(clingo_solve_handle_resume(hnd_.get())); }
459
467 [[nodiscard]] auto model() -> std::optional<ConstModel> {
468 clingo_model_t const *mdl = Detail::call<clingo_solve_handle_model>(hnd_.get());
469 return mdl != nullptr ? std::make_optional<ConstModel>(mdl) : std::nullopt;
470 }
471
478 [[nodiscard]] auto last() const -> std::optional<ConstModel> {
479 clingo_model_t const *mdl = Detail::call<clingo_solve_handle_last>(hnd_.get());
480 return mdl != nullptr ? std::make_optional<ConstModel>(mdl) : std::nullopt;
481 }
482
491 auto const *lits = static_cast<clingo_literal_t *>(nullptr);
492 auto size = size_t{0};
493 Detail::handle_error(clingo_solve_handle_core(hnd_.get(), &lits, &size));
494 return {lits, size};
495 }
496
508 [[nodiscard]] auto wait(std::optional<double> timeout) -> bool {
509 return Detail::call<clingo_solve_handle_wait>(hnd_.get(), timeout ? *timeout : -1);
510 }
511
513 [[nodiscard]] auto begin() -> iterator { return iterator{*this}; }
515 [[nodiscard]] auto end() -> sentinel {
516 static_cast<void>(this);
517 return sentinel{};
518 }
519
520 private:
521 friend class Control;
522
523 struct Free {
524 Free() {
525 // NOTE: We assume that solve is only called during normal
526 // operation - not during exception handling.
527 assert(std::uncaught_exceptions() == 0);
528 }
529 void operator()(clingo_solve_handle_t *hnd) const noexcept(false) {
530 try {
531 // NOTE: currently the solve handle calls cancel and then
532 // deletes clasp's underlying solve handle. I am not sure
533 // whether this can actually throw or not.
534 Detail::handle_error(clingo_solve_handle_close(hnd));
535 } catch (...) {
536 if (std::uncaught_exceptions() == 1) {
537 throw;
538 }
539 }
540 }
541 };
542
543 std::unique_ptr<clingo_solve_handle_t, Free> hnd_;
544};
545static_assert(std::input_iterator<SolveHandle::iterator>);
546static_assert(std::sentinel_for<SolveHandle::sentinel, SolveHandle::iterator>);
547
549
550namespace Detail {
551
552static constexpr clingo_solve_event_handler_t c_solve_event_handler{
553 [](clingo_model_t *model, void *data, bool *goon) -> bool {
554 CLINGO_TRY {
555 auto *hnd = static_cast<SolveEventHandler *>(data);
556 assert(hnd != nullptr);
557 auto mdl = Model{model};
558 *goon = hnd->model(mdl);
559 return true;
560 }
561 CLINGO_CATCH;
562 },
563 [](int64_t const *values, size_t size, void *data) -> bool {
564 CLINGO_TRY {
565 auto *hnd = static_cast<SolveEventHandler *>(data);
566 assert(hnd != nullptr);
567 hnd->unsat({values, size});
568 }
569 CLINGO_CATCH;
570 },
571 [](clingo_stats_t *stats, void *data) -> bool {
572 CLINGO_TRY {
573 auto *hnd = static_cast<SolveEventHandler *>(data);
574 assert(hnd != nullptr);
575 std::string_view user_step = "user_step";
576 std::string_view user_accu = "user_accu";
577 uint64_t root = Detail::call<clingo_stats_root>(stats);
578 uint64_t step = Detail::call<clingo_stats_map_add_subkey>(stats, root, user_step.data(), user_step.size(),
580 uint64_t accu = Detail::call<clingo_stats_map_add_subkey>(stats, root, user_accu.data(), user_accu.size(),
582 hnd->stats(Stats{stats, step}, Stats{stats, accu});
583 }
584 CLINGO_CATCH;
585 },
586 [](clingo_solve_result_bitset_t result, void *data) -> void {
587 auto *hnd = static_cast<SolveEventHandler *>(data);
588 assert(hnd != nullptr);
589 hnd->finish(static_cast<SolveResult>(result));
590 },
591 nullptr,
592};
593
594} // namespace Detail
595
596} // namespace Clingo
A base that maps signatures to atom bases, and captures term and theory bases.
Definition base.hh:608
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:179
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:311
void stats(Stats step, Stats accu)
Callback to update solving statistics.
Definition solve.hh:317
void finish(SolveResult result) noexcept
Callback to handle the end of solving.
Definition solve.hh:325
SolveEventHandler()=default
The default constructor.
auto model(Model model) -> bool
Callback to interact with the model found during solving.
Definition solve.hh:306
virtual ~SolveEventHandler()=default
The default destructor.
Iterator to iterate over models found during solving.
Definition solve.hh:340
auto operator++() -> iterator &
Increment the iterator to the next model.
Definition solve.hh:369
std::ptrdiff_t difference_type
The difference type.
Definition solve.hh:345
ConstModel & reference
The reference type.
Definition solve.hh:351
friend auto operator==(iterator const &a, sentinel const &b) -> bool
Check whether all models have been exhausted.
Definition solve.hh:398
std::input_iterator_tag iterator_category
The iterator category.
Definition solve.hh:343
ConstModel * pointer
The pointer type.
Definition solve.hh:349
friend auto operator==(const iterator &a, const iterator &b) -> bool
Compare iterators for equality.
Definition solve.hh:391
auto operator->() const -> pointer
Member access operator to get a pointer to the current model.
Definition solve.hh:364
ConstModel value_type
The value type, which are models.
Definition solve.hh:347
iterator()=default
The default constructor.
auto operator++(int) -> iterator
Postfix increment the iterator.
Definition solve.hh:378
auto operator*() const -> reference
Get a reference to the current model.
Definition solve.hh:359
Class to control a running search.
Definition solve.hh:335
void cancel()
Cancel the current search.
Definition solve.hh:444
auto begin() -> iterator
Get an iterator to iterate over models found during solving.
Definition solve.hh:513
auto end() -> sentinel
Get a sentinel to indicate that all models have been exhausted.
Definition solve.hh:515
auto model() -> std::optional< ConstModel >
Get the current model.
Definition solve.hh:467
void resume()
Resume the current search.
Definition solve.hh:458
auto get() const -> SolveResult
Get the solve result.
Definition solve.hh:437
auto core() const -> ProgramLiteralSpan
Get the unsatisfiable core.
Definition solve.hh:490
friend auto c_cast(SolveHandle const &x) -> clingo_solve_handle_t *
Cast the solve handle to its C representation.
Definition solve.hh:429
auto last() const -> std::optional< ConstModel >
Get the last model.
Definition solve.hh:478
SolveHandle(clingo_solve_handle_t *hnd)
Constructor from the underlying C representation.
Definition solve.hh:424
iterator::difference_type difference_type
The difference type.
Definition solve.hh:411
auto wait(std::optional< double > timeout) -> bool
Wait for the next model or solve result.
Definition solve.hh:508
void close()
Close the solve handle.
Definition solve.hh:452
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:78
int32_t clingo_weight_t
Signed integer type for weights in sum aggregates and minimize constraints.
Definition core.h:84
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:110
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:60
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:54
@ clingo_solve_result_interrupted
The last solve call was interrupted.
Definition solve.h:57
@ clingo_solve_result_exhausted
The last solve call completely exhausted the search space.
Definition solve.h:56
@ clingo_solve_result_unsatisfiable
The last solve call did not find a solution.
Definition solve.h:55
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:305
@ model
The model represents a stable model.
@ tuple
Theory tuples "(t1,...,tn)".
@ symbols
Whether to write symbols in a structured format.
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:338
The solve event handler interface.
Definition solve.h:72