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 virtual ~SolveEventHandler() = default;
295
300 auto model(Model model) -> bool { return do_model(model); }
301
305 void unsat(SumSpan lower_bound) { do_unsat(lower_bound); }
306
311 void stats(Stats step, Stats accu) { do_stats(step, accu); }
312
319 void finish(SolveResult result) noexcept { do_finish(result); }
320
321 private:
322 virtual auto do_model([[maybe_unused]] Model model) -> bool { return true; }
323 virtual void do_unsat([[maybe_unused]] SumSpan lower_bound) {}
324 virtual void do_stats([[maybe_unused]] Stats step, [[maybe_unused]] Stats accu) {}
325 virtual void do_finish([[maybe_unused]] SolveResult result) noexcept {}
326};
327
330 public:
332 struct sentinel {};
334 class iterator {
335 public:
337 using iterator_category = std::input_iterator_tag;
339 using difference_type = std::ptrdiff_t;
346
350 iterator() = default;
351
353 auto operator*() const -> reference {
354 return mdl_.value(); // NOLINT
355 }
356
358 auto operator->() const -> pointer {
359 return &mdl_.value(); // NOLINT
360 }
361
363 auto operator++() -> iterator & {
364 hnd_->resume();
365 mdl_ = hnd_->model();
366 return *this;
367 }
368
372 auto operator++(int) -> iterator {
373 iterator tmp = *this;
374 ++(*this);
375 return tmp;
376 }
377
385 friend auto operator==(const iterator &a, const iterator &b) -> bool { return a.hnd_ == b.hnd_; }
386
392 friend auto operator==(iterator const &a, [[maybe_unused]] sentinel const &b) -> bool {
393 return !a.mdl_.has_value();
394 }
395
396 private:
397 friend class SolveHandle;
398
399 explicit iterator(SolveHandle &hnd) : hnd_{&hnd} { operator++(); }
400
401 SolveHandle *hnd_ = nullptr;
402 mutable std::optional<value_type> mdl_;
403 };
412
418 explicit SolveHandle(clingo_solve_handle_t *hnd) : hnd_{hnd} {}
419
423 friend auto c_cast(SolveHandle const &x) -> clingo_solve_handle_t * { return x.hnd_.get(); }
424
431 [[nodiscard]] auto get() const -> SolveResult {
432 return SolveResult{Detail::call<clingo_solve_handle_get>(hnd_.get())};
433 }
434
438 void cancel() { Detail::handle_error(clingo_solve_handle_cancel(hnd_.get())); }
439
444 void resume() { Detail::handle_error(clingo_solve_handle_resume(hnd_.get())); }
445
453 [[nodiscard]] auto model() -> std::optional<ConstModel> {
454 clingo_model_t const *mdl = Detail::call<clingo_solve_handle_model>(hnd_.get());
455 return mdl != nullptr ? std::make_optional<ConstModel>(mdl) : std::nullopt;
456 }
457
464 [[nodiscard]] auto last() const -> std::optional<ConstModel> {
465 clingo_model_t const *mdl = Detail::call<clingo_solve_handle_last>(hnd_.get());
466 return mdl != nullptr ? std::make_optional<ConstModel>(mdl) : std::nullopt;
467 }
468
476 [[nodiscard]] auto core() const -> ProgramLiteralSpan {
477 auto const *lits = static_cast<clingo_literal_t *>(nullptr);
478 auto size = size_t{0};
479 Detail::handle_error(clingo_solve_handle_core(hnd_.get(), &lits, &size));
480 return {lits, size};
481 }
482
494 [[nodiscard]] auto wait(std::optional<double> timeout) -> bool {
495 return Detail::call<clingo_solve_handle_wait>(hnd_.get(), timeout ? *timeout : -1);
496 }
497
499 [[nodiscard]] auto begin() -> iterator { return iterator{*this}; }
501 [[nodiscard]] auto end() -> sentinel {
502 static_cast<void>(this);
503 return sentinel{};
504 }
505
506 private:
507 friend class Control;
508
509 struct Close {
510 void operator()(clingo_solve_handle_t *ptr) const noexcept { clingo_solve_handle_close(ptr); }
511 };
512
513 std::unique_ptr<clingo_solve_handle_t, Close> hnd_;
514};
515static_assert(std::input_iterator<SolveHandle::iterator>);
516static_assert(std::sentinel_for<SolveHandle::sentinel, SolveHandle::iterator>);
517
519
520namespace Detail {
521
522static constexpr clingo_solve_event_handler_t c_solve_event_handler{
523 [](clingo_model_t *model, void *data, bool *goon) -> bool {
524 CLINGO_TRY {
525 auto *hnd = static_cast<SolveEventHandler *>(data);
526 assert(hnd != nullptr);
527 auto mdl = Model{model};
528 *goon = hnd->model(mdl);
529 return true;
530 }
531 CLINGO_CATCH;
532 },
533 [](int64_t const *values, size_t size, void *data) -> bool {
534 CLINGO_TRY {
535 auto *hnd = static_cast<SolveEventHandler *>(data);
536 assert(hnd != nullptr);
537 hnd->unsat({values, size});
538 }
539 CLINGO_CATCH;
540 },
541 [](clingo_stats_t *stats, void *data) -> bool {
542 CLINGO_TRY {
543 auto *hnd = static_cast<SolveEventHandler *>(data);
544 assert(hnd != nullptr);
545 std::string_view user_step = "user_step";
546 std::string_view user_accu = "user_accu";
547 uint64_t root = Detail::call<clingo_stats_root>(stats);
548 uint64_t step = Detail::call<clingo_stats_map_add_subkey>(stats, root, user_step.data(), user_step.size(),
550 uint64_t accu = Detail::call<clingo_stats_map_add_subkey>(stats, root, user_accu.data(), user_accu.size(),
552 hnd->stats(Stats{stats, step}, Stats{stats, accu});
553 }
554 CLINGO_CATCH;
555 },
556 [](clingo_solve_result_bitset_t result, void *data) -> void {
557 auto *hnd = static_cast<SolveEventHandler *>(data);
558 assert(hnd != nullptr);
559 hnd->finish(static_cast<SolveResult>(result));
560 },
561 nullptr,
562};
563
564} // namespace Detail
565
566} // 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:159
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
void unsat(SumSpan lower_bound)
Callback to inspect lower bounds found during solving.
Definition solve.hh:305
void stats(Stats step, Stats accu)
Callback to update solving statistics.
Definition solve.hh:311
void finish(SolveResult result) noexcept
Callback to handle the end of solving.
Definition solve.hh:319
auto model(Model model) -> bool
Callback to interact with the model found during solving.
Definition solve.hh:300
virtual ~SolveEventHandler()=default
The default destructor.
Iterator to iterate over models found during solving.
Definition solve.hh:334
auto operator++() -> iterator &
Increment the iterator to the next model.
Definition solve.hh:363
std::ptrdiff_t difference_type
The difference type.
Definition solve.hh:339
ConstModel & reference
The reference type.
Definition solve.hh:345
friend auto operator==(iterator const &a, sentinel const &b) -> bool
Check whether all models have been exhausted.
Definition solve.hh:392
std::input_iterator_tag iterator_category
The iterator category.
Definition solve.hh:337
ConstModel * pointer
The pointer type.
Definition solve.hh:343
friend auto operator==(const iterator &a, const iterator &b) -> bool
Compare iterators for equality.
Definition solve.hh:385
auto operator->() const -> pointer
Member access operator to get a pointer to the current model.
Definition solve.hh:358
ConstModel value_type
The value type, which are models.
Definition solve.hh:341
iterator()=default
The default constructor.
auto operator++(int) -> iterator
Postfix increment the iterator.
Definition solve.hh:372
auto operator*() const -> reference
Get a reference to the current model.
Definition solve.hh:353
Class to control a running search.
Definition solve.hh:329
void cancel()
Cancel the current search.
Definition solve.hh:438
auto begin() -> iterator
Get an iterator to iterate over models found during solving.
Definition solve.hh:499
auto end() -> sentinel
Get a sentinel to indicate that all models have been exhausted.
Definition solve.hh:501
auto model() -> std::optional< ConstModel >
Get the current model.
Definition solve.hh:453
void resume()
Resume the current search.
Definition solve.hh:444
auto get() const -> SolveResult
Get the solve result.
Definition solve.hh:431
auto core() const -> ProgramLiteralSpan
Get the unsatisfiable core.
Definition solve.hh:476
friend auto c_cast(SolveHandle const &x) -> clingo_solve_handle_t *
Cast the solve handle to its C representation.
Definition solve.hh:423
auto last() const -> std::optional< ConstModel >
Get the last model.
Definition solve.hh:464
SolveHandle(clingo_solve_handle_t *hnd)
Constructor from the underlying C representation.
Definition solve.hh:418
iterator::difference_type difference_type
The difference type.
Definition solve.hh:405
auto wait(std::optional< double > timeout) -> bool
Wait for the next model or solve result.
Definition solve.hh:494
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.
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_VISIBILITY_DEFAULT void clingo_solve_handle_close(clingo_solve_handle_t *handle)
Stops the running search and releases the handle.
@ 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.
std::span< Sum const > SumSpan
A span of sums.
Definition core.hh:513
clingo_literal_t ProgramLiteral
A program literal.
Definition core.hh:485
clingo_id_t ProgramId
A program id used for various kinds of indices.
Definition core.hh:475
std::span< ProgramLiteral const > ProgramLiteralSpan
A span of program literals.
Definition core.hh:487
std::span< clingo_weight_t const > WeightSpan
A span of weights.
Definition core.hh:503
@ accu
Indicate accumulated profiling data.
@ step
Indicate per step profiling data.
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:332
The solve event handler interface.
Definition solve.h:74