Clingo
Loading...
Searching...
No Matches
base.hh
1#pragma once
2
3#include <clingo/ground/instantiator.hh>
4#include <clingo/ground/term.hh>
5
6#include <clingo/core/symbol.hh>
7
8#include <clingo/util/index_sequence.hh>
9#include <clingo/util/ordered_map.hh>
10#include <clingo/util/ordered_set.hh>
11#include <clingo/util/small_vector.hh>
12
13namespace CppClingo::Ground {
14
17
21using VariableVec = VariableSet::values_container_type;
22
24// NOLINTNEXTLINE(performance-enum-size)
25enum class StateAtom : uint64_t {
27 fact = 0,
29 derived = 1,
39 unknown = 2,
40};
41
43struct AtomInfo {
44 uint64_t id : 62;
46};
47
48static_assert(sizeof(AtomInfo) == sizeof(uint64_t));
49
51using SymbolicAtom = std::pair<Symbol, AtomInfo>;
52
54enum class AtomUpdate : uint8_t {
55 added = 0,
56 changed = 1,
57 unchanged = 2,
58};
59
65 public:
74
76 [[nodiscard]] auto begin(MatcherType type) const -> size_t {
77 if (type == MatcherType::new_atoms) {
78 return old_offset_;
79 }
80 return 0;
81 }
82
84 [[nodiscard]] auto end(MatcherType type) const -> size_t {
85 if (type == MatcherType::old_atoms) {
86 return old_offset_;
87 }
88 return all_offset_;
89 }
90
92 [[nodiscard]] auto contains(size_t index, MatcherType type) const -> bool {
93 return begin(type) <= index && index < end(type);
94 }
95
97 [[nodiscard]] auto has_update(size_t size) const -> bool { return all_offset_ < size; }
98
103 void update(size_t generation, size_t size) {
104 // initialize the domain
105 // (all atoms are marked as new)
106 if (generation == 0) {
107 generation_ = 0;
108 old_offset_ = 0;
109 all_offset_ = size;
110 }
111 // the generation has been incremented by one
112 // (freshly added atoms are marked new)
113 else if (generation_ + 1 == generation) {
114 generation_ = generation;
115 old_offset_ = all_offset_;
116 all_offset_ = size;
117 // the generation has been incremented by more than one
118 // (all atoms are marked old)
119 } else if (generation_ + 1 < generation) {
120 generation_ = generation;
121 old_offset_ = size;
122 all_offset_ = size;
123 }
124 }
125
126 private:
128 size_t old_offset_ = 0;
130 size_t all_offset_ = 0;
132 size_t generation_ = 0;
133};
134
140 public:
142 virtual ~BaseContext() = default;
143};
144
148template <class KeyType, class BaseType> class BaseImpl {
149 public:
151 using Key = KeyType;
152
154 [[nodiscard]] auto begin(MatcherType type) const -> size_t { return counts_.begin(type); }
155
157 [[nodiscard]] auto end(MatcherType type) const -> size_t { return counts_.end(type); }
158
160 [[nodiscard]] auto contains(Key const &sym, MatcherType type) const -> std::optional<size_t> {
161 if (auto idx = base().index(sym); counts_.contains(idx, type)) {
162 return idx;
163 }
164 return std::nullopt;
165 }
166
168 void update(size_t generation) { counts_.update(generation, base().size()); }
169
171 void ensure(size_t generation) { update(generation > 0 ? generation - 1 : 0); }
172
176 template <class T> auto context() -> T & {
177 if (context_ != nullptr) {
178 if (auto res = dynamic_cast<T *>(context_.get()); res != nullptr) {
179 return *res;
180 }
181 throw std::bad_cast();
182 }
183 context_ = std::make_unique<T>();
184 return static_cast<T &>(*context_);
185 }
186
188 void clear_context() { context_ = nullptr; }
189
191 [[nodiscard]] auto has_update() const -> bool { return counts_.has_update(base().size()); }
192
193 private:
194 friend BaseType;
195 BaseImpl() = default;
196
197 [[nodiscard]] auto base() -> BaseType & { return *static_cast<BaseType *>(this); }
198 [[nodiscard]] auto base() const -> BaseType const & { return *static_cast<BaseType const *>(this); }
199
200 GenerationCounts counts_;
201 std::unique_ptr<BaseContext> context_;
202};
203
212class AtomBase : public BaseImpl<Symbol, AtomBase> {
213 public:
216
220 [[nodiscard]] auto domain() const {
221 for (auto n = derived_.size(); domain_offset_ < n; ++domain_offset_) {
222 if (atoms_.nth(derived_[domain_offset_])->second.state != StateAtom::fact) {
223 return false;
224 }
225 }
226 return true;
227 }
232 auto is_fact(Symbol sym) const -> bool {
233 auto it = atoms_.find(sym);
234 return it != atoms_.end() && it->second.state == StateAtom::fact;
235 }
236
238 [[nodiscard]] auto find(Symbol const &sym) -> std::optional<MapAtom::iterator> {
239 auto it = atoms_.find(sym);
240 if (it != atoms_.end() && it->second.state != StateAtom::unknown) {
241 return it;
242 }
243 return std::nullopt;
244 }
245
247 template <class Gen> auto add(Symbol atom, StateAtom state, Gen &&gen) -> std::pair<MapAtom::iterator, AtomUpdate> {
248 auto [it, ins] = atoms_.try_emplace(atom, 0, state);
249 if (ins) {
250 it.value().id = std::invoke(std::forward<Gen>(gen));
251 if (state != StateAtom::unknown) {
252 derived_.add(atom_index_(it));
253 }
254 return {it, AtomUpdate::added};
255 }
256 auto &prev = it.value();
257 if (state < prev.state) {
258 if (prev.state == StateAtom::unknown) {
259 prev.state = state;
260 derived_.add(atom_index_(it));
261 return {it, AtomUpdate::added};
262 }
263 prev.state = state;
264 return {it, AtomUpdate::changed};
265 }
266 return {it, AtomUpdate::unchanged};
267 }
268
270 [[nodiscard]] auto size() const -> size_t { return derived_.size(); }
272 [[nodiscard]] auto num_shown() const -> size_t { return show_offset_; }
273
277 auto index(Symbol const &sym) const -> size_t {
278 if (auto it = atoms_.find(sym); it != atoms_.end() && it->second.state != StateAtom::unknown) {
279 return derived_.find(atom_index_(it));
280 }
281 return size();
282 }
284 auto nth(size_t i) const -> MapAtom::const_iterator { return atoms_.nth(derived_[i]); }
286 auto nth(size_t i) -> MapAtom::iterator { return atoms_.nth(derived_[i]); }
287
291 for (auto const &[sym, atom] : atoms_) {
292 gc.mark(sym);
293 }
294 }
295
299 [[nodiscard]] auto mark_shown() -> size_t { return std::exchange(show_offset_, size()); }
300
304 [[nodiscard]] auto mark_negated() -> size_t { return std::exchange(negate_offset_, size()); }
305
309 [[nodiscard]] auto mark_projected() -> size_t { return std::exchange(project_offset_, size()); }
310
318 template <class Pred> void simplify(Pred const &pred, size_t &rem, size_t &fact) {
319 // NOTE: the show offset can be zero for auxiliary domains
320 assert(show_offset_ == 0 || show_offset_ == size());
321 assert(negate_offset_ == 0 || negate_offset_ == size());
322 assert(project_offset_ == 0 || project_offset_ == size());
323 auto true_atoms = SymbolVec{};
324 erase_if(atoms_, [&](SymbolicAtom const &item) {
325 if (item.second.state == StateAtom::unknown) {
326 ++rem;
327 return true;
328 }
329 auto tv = pred(item.second.id);
330 if (tv == TruthValue::bot) {
331 ++rem;
332 return true;
333 }
334 if (tv == TruthValue::top && item.second.state != StateAtom::fact) {
335 ++fact;
336 true_atoms.emplace_back(item.first);
337 }
338 return false;
339 });
340 for (auto const &sym : true_atoms) {
341 atoms_.find(sym).value().state = StateAtom::fact;
342 }
343 derived_.assign(0, atoms_.size());
344 assert(derived_.size() == atoms_.size());
345 domain_offset_ = 0;
346 show_offset_ = show_offset_ > 0 ? size() : 0;
347 negate_offset_ = negate_offset_ > 0 ? size() : 0;
348 project_offset_ = project_offset_ > 0 ? size() : 0;
349 }
350
351 private:
352 [[nodiscard]] auto atom_index_(MapAtom::const_iterator it) const -> size_t {
353 return static_cast<size_t>(std::distance(atoms_.cbegin(), it));
354 }
355
356 MapAtom atoms_;
358 size_t mutable domain_offset_ = 0;
359 size_t show_offset_ = 0;
360 size_t negate_offset_ = 0;
361 size_t project_offset_ = 0;
362};
363
365using UAtomBase = std::unique_ptr<AtomBase>;
366
369 public:
371 ProjectState(String name, size_t vars, AtomBase &base, UTerm p_head, UTerm p_body)
372 : name_{name}, base_{&base}, p_head_{std::move(p_head)}, p_body_{std::move(p_body)} {
373 ass_.resize(vars);
374 }
376 [[nodiscard]] auto base() const -> AtomBase & { return *base_; }
378 [[nodiscard]] auto p_base() -> AtomBase & { return p_base_; }
380 [[nodiscard]] auto name() const -> String const & { return *name_; }
384 void init(InstantiationContext const &ctx, size_t gen);
385
386 private:
387 SharedString name_;
388 AtomBase *base_;
389 AtomBase p_base_;
390 UTerm p_head_;
391 UTerm p_body_;
392 Assignment ass_;
393 size_t imported_ = 0;
394};
396using UProjectState = std::unique_ptr<ProjectState>;
397
402
405
407class Bases {
408 public:
412 [[nodiscard]] auto add_base(std::tuple<String, size_t, bool> sig) -> Ground::AtomBase &;
413
417 [[nodiscard]] auto get_base(std::tuple<String, size_t, bool> sig) const -> Ground::AtomBase *;
418
420 [[nodiscard]] auto add_project(SymbolStore &store, Ground::UTerm const &term, Ground::AtomBase &base)
421 -> std::pair<Ground::UTerm, ProjectState *>;
422
424 [[nodiscard]] auto atoms() const -> BaseMap const & { return atoms_; }
426 [[nodiscard]] auto projected() const -> ProjectMap const & { return projected_; }
427
429 void clear_aux();
430
431 private:
432 BaseMap atoms_;
433 BaseMap aux_;
434 ProjectMap projected_;
435};
436
438class State {
439 public:
441 virtual ~State() = default;
443 virtual void output(Logger &log, SymbolStore &store, OutputStm &out) = 0;
444};
446using UState = std::unique_ptr<State>;
448using UStateVec = std::vector<UState>;
449
451
452} // namespace CppClingo::Ground
An atom base used to store derivable atoms and associated state.
Definition base.hh:212
auto domain() const
Check if the base is domain.
Definition base.hh:220
auto mark_negated() -> size_t
Mark derived atoms as shown.
Definition base.hh:304
auto is_fact(Symbol sym) const -> bool
Check if the given atom is a fact.
Definition base.hh:232
auto num_shown() const -> size_t
Get the number of shown atoms.
Definition base.hh:272
auto mark_projected() -> size_t
Mark derived atoms as projected.
Definition base.hh:309
auto find(Symbol const &sym) -> std::optional< MapAtom::iterator >
Check if the base contains the given atom.
Definition base.hh:238
Util::ordered_map< Symbol, AtomInfo > MapAtom
Map containing the atoms.
Definition base.hh:215
auto size() const -> size_t
Get the number of derived atoms.
Definition base.hh:270
auto add(Symbol atom, StateAtom state, Gen &&gen) -> std::pair< MapAtom::iterator, AtomUpdate >
Add an atom to the base.
Definition base.hh:247
auto nth(size_t i) const -> MapAtom::const_iterator
Get the i-th atom in the base.
Definition base.hh:284
void simplify(Pred const &pred, size_t &rem, size_t &fact)
Simplify the atom base.
Definition base.hh:318
auto index(Symbol const &sym) const -> size_t
Get the atom index of the given symbol.
Definition base.hh:277
auto nth(size_t i) -> MapAtom::iterator
Get the i-th atom in the base.
Definition base.hh:286
auto mark_shown() -> size_t
Mark derived atoms as shown.
Definition base.hh:299
void mark(SymbolCollector &gc)
Mark all symbols held by the base.
Definition base.hh:289
A context object.
Definition base.hh:139
virtual ~BaseContext()=default
Destroy the context.
The base implementation of an atom base.
Definition base.hh:148
void ensure(size_t generation)
Ensure that atoms are added to the given generation.
Definition base.hh:171
auto context() -> T &
Get the context of the base with the desired type.
Definition base.hh:176
auto has_update() const -> bool
Check if the base has an update.
Definition base.hh:191
KeyType Key
The key identifies an atom and is usually associated with further state.
Definition base.hh:151
auto begin(MatcherType type) const -> size_t
Get the index of the first atom in the given generation.
Definition base.hh:154
void update(size_t generation)
Update the generation counts.
Definition base.hh:168
auto end(MatcherType type) const -> size_t
Get the index plus one of the last atom in the given generation.
Definition base.hh:157
void clear_context()
Clear the current context.
Definition base.hh:188
auto contains(Key const &sym, MatcherType type) const -> std::optional< size_t >
Check if the base contains the given atom with in the given generation.
Definition base.hh:160
The base for all atoms and terms.
Definition base.hh:407
auto projected() const -> ProjectMap const &
Get the map of projected atoms.
Definition base.hh:426
auto add_base(std::tuple< String, size_t, bool > sig) -> Ground::AtomBase &
Add an atom base.
auto atoms() const -> BaseMap const &
Get the atom map.
Definition base.hh:424
void clear_aux()
Clear auxiliary atom bases.
auto add_project(SymbolStore &store, Ground::UTerm const &term, Ground::AtomBase &base) -> std::pair< Ground::UTerm, ProjectState * >
Add a base for a projected atom.
auto get_base(std::tuple< String, size_t, bool > sig) const -> Ground::AtomBase *
Get a base for the given signature.
Helper class to manage generation counts.
Definition base.hh:64
auto has_update(size_t size) const -> bool
Check if there is an update.
Definition base.hh:97
auto contains(size_t index, MatcherType type) const -> bool
Check if the given index belongs to the given generation.
Definition base.hh:92
auto end(MatcherType type) const -> size_t
Get the index plus one of the last atom in the given generation.
Definition base.hh:84
void update(size_t generation, size_t size)
Update the current generations.
Definition base.hh:103
auto begin(MatcherType type) const -> size_t
Update the generation counts.
Definition base.hh:76
Context object to capture state used during instantiation.
Definition instantiator.hh:17
The state capturing the base of a projection.
Definition base.hh:368
ProjectState(String name, size_t vars, AtomBase &base, UTerm p_head, UTerm p_body)
Initialize the state.
Definition base.hh:371
auto base() const -> AtomBase &
Get the base of the unprojected literal.
Definition base.hh:376
void init(InstantiationContext const &ctx, size_t gen)
Initialize the projected base.
auto name() const -> String const &
Get the auxiliary name of projected literal.
Definition base.hh:380
auto p_base() -> AtomBase &
Get the base of the projected literal.
Definition base.hh:378
Class to store state for grounding.
Definition base.hh:438
virtual ~State()=default
Destructor.
virtual void output(Logger &log, SymbolStore &store, OutputStm &out)=0
Output delayed literals.
Simple logger to report message to stderr or via a callback.
Definition logger.hh:63
Interface to output statements.
Definition output.hh:90
Class managing the lifetime of a String.
Definition symbol.hh:93
Reference to a string stored in a symbol store.
Definition symbol.hh:18
Helper class to mark owned symbols.
Definition symbol.hh:429
void mark(Symbol const &sym)
Mark a symbol and its descendants.
A store for symbols.
Definition symbol.hh:454
Variant-like class to store symbols stored in a symbol store.
Definition symbol.hh:225
Container to store integer sequences.
Definition index_sequence.hh:15
void assign(T l, T r)
Set the sequence to the interval [l,r-1].
Definition index_sequence.hh:83
void add(T value)
Add an integer to the sequence.
Definition index_sequence.hh:69
auto size() const -> size_t
Get the number of indices in the sequence.
Definition index_sequence.hh:115
auto find(T value) const -> size_t
Check if the sequence contains an element.
Definition index_sequence.hh:102
std::vector< std::optional< Symbol > > Assignment
Assignment mapping variables to symbols.
Definition symbol.hh:222
std::vector< Symbol > SymbolVec
A vector of symbols.
Definition symbol.hh:220
@ top
Indicate a true expression.
@ bot
Indicate a false expression.
std::unique_ptr< State > UState
A unique pointer to a state.
Definition base.hh:446
Util::ordered_map< std::tuple< String, size_t, bool >, UAtomBase > BaseMap
A map from signatures to atom bases.
Definition base.hh:404
Util::ordered_map< Ground::UTerm, UProjectState > ProjectMap
A map from a terms with projections associated state used during grounding.
Definition base.hh:401
std::pair< Symbol, AtomInfo > SymbolicAtom
An atom consisting of a symbol and its (mutable) state.
Definition base.hh:51
AtomUpdate
Enumeration indicating state updates of atoms.
Definition base.hh:54
std::unique_ptr< AtomBase > UAtomBase
A unique pointer holding a base.
Definition base.hh:365
VariableSet::values_container_type VariableVec
A vector of variables.
Definition base.hh:21
std::vector< UState > UStateVec
A vector of states.
Definition base.hh:448
Util::ordered_set< size_t > VariableSet
A set of variables.
Definition base.hh:19
StateAtom
Enumeration to capture the state of an atom.
Definition base.hh:25
std::unique_ptr< ProjectState > UProjectState
Unique pointer for ProjectState.
Definition base.hh:396
@ unchanged
An atom whose state did not change.
@ added
A freshly added atom.
@ derived
Indicates that the atom is derived by some rule but not a fact.
@ unknown
Indicates that the atom has not yet been derived by a rule.
@ fact
Indicates that the atom is derived by a fact.
MatcherType
Enumeration of matcher types.
Definition instantiator.hh:48
@ old_atoms
Indicates a matcher for freshly added atoms.
std::unique_ptr< Term > UTerm
A unique pointer holding a term.
Definition term.hh:33
tsl::ordered_set< Key, Hash, KeyEqual, Allocator, ValueTypeContainer, IndexType > ordered_set
Alias for ordered sets.
Definition ordered_set.hh:15
tsl::ordered_map< Key, T, Hash, KeyEqual, Allocator, ValueTypeContainer, IndexType > ordered_map
Alias for ordered maps.
Definition ordered_map.hh:16
Capture the state of an atom.
Definition base.hh:43
StateAtom state
The atom state.
Definition base.hh:45
uint64_t id
A unique id among all atoms.
Definition base.hh:44