1212#include < cassert>
1313#include < iostream>
1414
15+ // #define TRACE_ON
16+
1517namespace datalog
1618{
1719
@@ -193,7 +195,6 @@ static bool bind(ATOM_TYPE &atom, const GROUND_TYPE &fact, index_sequence<Is...>
193195template <typename RELATION_TYPE>
194196static bool bind (typename RELATION_TYPE::Atom &atom, const RELATION_TYPE &fact)
195197{
196- // unbind<RELATION_TYPE>(atom);
197198 constexpr size_t tupleSize = tuple_size<typename RELATION_TYPE::TupleType>::value;
198199 return bind<typename RELATION_TYPE::Atom, typename RELATION_TYPE::TupleType>(atom, fact, make_index_sequence<tupleSize>{});
199200}
@@ -205,9 +206,11 @@ struct Rule
205206 typedef HEAD_RELATION HeadRelationType;
206207 typedef typename HEAD_RELATION::Atom HeadType;
207208 HeadType head;
208- typedef tuple<BODY_RELATIONs...> BodyRelations;
209209 typedef tuple<typename BODY_RELATIONs::Atom...> BodyType;
210210 BodyType body;
211+ typedef tuple<BODY_RELATIONs...> BodyRelations;
212+ typedef tuple<typename BODY_RELATIONs::Set::const_iterator...> BodyRelationsIteratorType;
213+ typedef tuple<const BODY_RELATIONs *...> SliceType;
211214
212215 // TODO:
213216 // You must sub-class to define rules
@@ -237,8 +240,6 @@ struct State
237240{
238241 typedef tuple<Set<RELATIONs>...> SetsOfRelationsType;
239242 SetsOfRelationsType relations;
240- typedef tuple<const RELATIONs *...> SliceType;
241- typedef tuple<typename RELATIONs::Set::const_iterator...> IteratorsArrayType;
242243
243244 size_t size () const {
244245 size_t totalSize = 0 ;
@@ -267,29 +268,35 @@ struct State
267268 return out;
268269 }
269270
270- static ostream &
271- print (ostream &out, const SliceType &slice)
272- {
273- apply ([&out](auto &&... args) { ((print (out, args), ...)); }, slice);
274- return out;
275- }
276-
271+ template <typename RULE_TYPE>
277272 struct Iterator
278273 {
274+ typedef typename RULE_TYPE::SliceType SliceType;
275+ typedef typename RULE_TYPE::BodyRelationsIteratorType RelationsIteratorType;
276+
279277 Iterator (const SetsOfRelationsType &relations) : relations(relations), iterators(initIterators(relations))
280278 {
281279 }
282280
281+ static ostream &
282+ print (ostream &out, const SliceType &slice)
283+ {
284+ apply ([&out](auto &&... args) { ((print (out, args), ...)); }, slice);
285+ return out;
286+ }
287+
283288 private:
284- template <size_t I, typename RELATION_TYPE>
285- void pick (const typename RELATION_TYPE::Set &relation,
286- const RELATION_TYPE *&sliceElement)
289+ template <size_t I>
290+ void pick (const SetsOfRelationsType &relations, SliceType &slice)
287291 {
292+ typedef typename tuple_element<I, typename RULE_TYPE::BodyRelations>::type RelationType;
288293 const auto &it = get<I>(iterators);
289- if (it != relation.end ())
294+ auto & sliceElement = get<I>(slice);
295+ const auto & relation = get<Set<RelationType>>(relations);
296+ if (it != relation.set .end ())
290297 {
291298 // TODO: avoid cast if possible
292- sliceElement = reinterpret_cast <const RELATION_TYPE *>(&*it);
299+ sliceElement = reinterpret_cast <const RelationType *>(&*it);
293300 }
294301 else
295302 {
@@ -301,27 +308,26 @@ struct State
301308 void pick (const SetsOfRelationsType &relations, SliceType &slice,
302309 index_sequence<Is...>)
303310 {
304- // cout << "[" << endl;
305- // ((pick<Is>(get<Is>(relations), get<Is>(slice))), ...);
306- ((pick<Is>(get<Is>(relations).set , get<Is>(slice))), ...);
307- // cout << "]" << endl;
311+ ((pick<Is>(relations, slice)), ...);
308312 }
309313
310314 template <size_t I>
311- bool next (const SetsOfRelationsType &relations, IteratorsArrayType &iterators,
315+ bool next (const SetsOfRelationsType &relations, RelationsIteratorType &iterators,
312316 bool &stop)
313317 {
318+ typedef typename tuple_element<I, typename RULE_TYPE::BodyRelations>::type RelationType;
319+
314320 bool iterationFinished = false ;
315321 if (not stop)
316322 {
317323 auto &it = get<I>(iterators);
318- const auto &end = get<I >(relations).set .end ();
324+ const auto &end = get<Set<RelationType> >(relations).set .end ();
319325 if (it != end)
320326 it++;
321327 if (it == end)
322328 {
323- it = get<I >(relations).set .begin ();
324- if (I == tuple_size<SetsOfRelationsType >::value - 1 )
329+ it = get<Set<RelationType> >(relations).set .begin ();
330+ if (I == tuple_size<RelationsIteratorType >::value - 1 )
325331 {
326332 iterationFinished = true ;
327333 }
@@ -335,7 +341,7 @@ struct State
335341 }
336342
337343 template <size_t ... Is>
338- bool next (const SetsOfRelationsType &relations, IteratorsArrayType &iterators,
344+ bool next (const SetsOfRelationsType &relations, RelationsIteratorType &iterators,
339345 index_sequence<Is...>)
340346 {
341347 bool stop = false ;
@@ -351,7 +357,7 @@ struct State
351357 SliceType next ()
352358 {
353359 SliceType slice;
354- auto indexSequence = make_index_sequence<tuple_size<SetsOfRelationsType >::value>{};
360+ auto indexSequence = make_index_sequence<tuple_size<RelationsIteratorType >::value>{};
355361 pick (relations, slice, indexSequence);
356362 iterationFinished = next (relations, iterators, indexSequence);
357363 #if 0
@@ -366,35 +372,38 @@ struct State
366372
367373 private:
368374 const SetsOfRelationsType &relations;
369- IteratorsArrayType iterators;
375+ RelationsIteratorType iterators;
370376 bool iterationFinished = false ;
371377
372- // RELATION_TYPE is really the set
373- template <typename RELATION_TYPE, typename ITERATOR_TYPE>
374- static void initIterator (const RELATION_TYPE &relation, ITERATOR_TYPE &iterator)
378+ template <size_t I>
379+ static void initIterator (const SetsOfRelationsType &relations, RelationsIteratorType &iterators)
375380 {
376- iterator = relation.begin ();
381+ typedef typename tuple_element<I, typename RULE_TYPE::BodyRelations>::type RelationType;
382+ auto & it = get<I>(iterators);
383+ const auto & relation = get<Set<RelationType>>(relations);
384+ it = relation.set .begin ();
377385 }
378386
379387 template <size_t ... Is>
380388 static void initIterators (const SetsOfRelationsType &relations,
381- IteratorsArrayType &iterators, index_sequence<Is...>)
389+ RelationsIteratorType &iterators, index_sequence<Is...>)
382390 {
383- ((initIterator (get <Is>(relations). set , get<Is>( iterators) )), ...);
391+ ((initIterator<Is>(relations, iterators)), ...);
384392 }
385393
386- static IteratorsArrayType initIterators (const SetsOfRelationsType &relations)
394+ static RelationsIteratorType initIterators (const SetsOfRelationsType &relations)
387395 {
388- IteratorsArrayType iterators;
396+ RelationsIteratorType iterators;
389397 initIterators (relations, iterators,
390- make_index_sequence<tuple_size<IteratorsArrayType >::value>{});
398+ make_index_sequence<tuple_size<RelationsIteratorType >::value>{});
391399 return iterators;
392400 }
393401 };
394402
395- Iterator iterator () const
403+ template <typename RULE_TYPE>
404+ Iterator<RULE_TYPE> it () const
396405 {
397- Iterator it{relations};
406+ Iterator<RULE_TYPE> it{relations};
398407 return it;
399408 }
400409};
@@ -413,42 +422,38 @@ static void unbind(const typename RULE_TYPE::BodyType &atoms)
413422 make_index_sequence<tuple_size<typename RULE_TYPE::BodyType>::value>{});
414423}
415424
416- template <size_t I, typename RULE_TYPE, typename ... RELATIONs >
417- static bool bind (typename RULE_TYPE::BodyType &atoms, // typedef tuple<typename BODY_RELATIONs::Atom...> BodyType;
418- const tuple<RELATIONs const *...> &slice)
425+ template <size_t I, typename RULE_TYPE>
426+ static bool bindBodyAtomsToSlice (typename RULE_TYPE::BodyType &atoms,
427+ const typename RULE_TYPE::SliceType &slice)
419428{
420- // get the fact in the slice that can potentially bind
421- typedef typename tuple_element<I, typename RULE_TYPE::BodyRelations>::type BodyRelationI;
422- auto factPtr = get<BodyRelationI const *>(slice);
429+ auto factPtr = get<I>(slice);
423430 bool success = false ;
424431 if (factPtr)
425432 {
426- const BodyRelationI &fact = *factPtr;
433+ const auto &fact = *factPtr;
427434 // get the atom
428- typename BodyRelationI::Atom &atom = get<I>(atoms);
435+ auto &atom = get<I>(atoms);
429436 // try to bind the atom with the fact
430437 success = bind (atom, fact);
431438 }
432439 return success;
433440}
434441
435- template <typename RULE_TYPE, typename ... RELATIONs, size_t ... Is>
436- static bool bind (typename RULE_TYPE::BodyType &atoms,
437- const tuple<RELATIONs const *...> &slice, index_sequence<Is...>)
442+ template <typename RULE_TYPE, size_t ... Is>
443+ static bool bindBodyAtomsToSlice (typename RULE_TYPE::BodyType &atoms,
444+ const typename RULE_TYPE::SliceType &slice, index_sequence<Is...>)
438445{
439- return ((bind <Is, RULE_TYPE, RELATIONs... >(atoms, slice)) and ...);
446+ return ((bindBodyAtomsToSlice <Is, RULE_TYPE>(atoms, slice)) and ...);
440447}
441448
442449// bind n atoms (of multiple relation types) with 1 slice (of multiple relation types)
443- template <typename RULE_TYPE, typename ... RELATIONs>
444- static bool bind (typename RULE_TYPE::BodyType &atoms,
445- const tuple<RELATIONs const *...> &slice)
450+ template <typename RULE_TYPE>
451+ static bool bindBodyAtomsToSlice (typename RULE_TYPE::BodyType &atoms, const typename RULE_TYPE::SliceType &slice)
446452{
447453 // unbind all the Variables
448454 unbind<RULE_TYPE>(atoms);
449455 // for each atom, bind with corresponding relation type in slice
450- return bind<RULE_TYPE, RELATIONs...>(atoms, slice,
451- make_index_sequence<tuple_size<typename RULE_TYPE::BodyType>::value>{});
456+ return bindBodyAtomsToSlice<RULE_TYPE>(atoms, slice, make_index_sequence<tuple_size<typename RULE_TYPE::BodyType>::value>{});
452457}
453458
454459template <typename VALUE_TYPE>
@@ -480,24 +485,23 @@ static RELATION_TYPE ground(const typename RELATION_TYPE::Atom &atom)
480485 return groundAtom;
481486}
482487
483-
484488template <typename RULE_TYPE, typename STATE_TYPE>
485489static Set<typename RULE_TYPE::HeadRelationType> applyRule (RULE_TYPE &rule, const STATE_TYPE &state)
486490{
487491 typedef typename RULE_TYPE::HeadRelationType HeadRelationType;
488492 Set<HeadRelationType> derivedFacts;
489- auto it = state.iterator ();
493+ auto it = state.template it <RULE_TYPE> ();
490494 while (it.hasNext ())
491495 {
492496 auto slice = it.next ();
493- if (bind <RULE_TYPE>(rule.body , slice))
497+ if (bindBodyAtomsToSlice <RULE_TYPE>(rule.body , slice))
494498 {
495499 // successful bind, therefore add (grounded) head atom to new state
496500 // cout << "successful bind of body" << endl;
497501 auto derivedFact = ground<HeadRelationType>(rule.head );
498- #if 1
502+ #ifdef TRACE_ON
499503 {
500- cout << " adding: " ;
504+ cout << " adding: " << typeid (HeadRelationType). name () << " " ;
501505 datalog::print<typename HeadRelationType::TupleType>(cout, derivedFact); // TODO: avoid need for type
502 506 cout << endl;
503507 }
@@ -556,8 +560,14 @@ static State<RELATIONs...> fixPoint(RuleSet<RULE_TYPEs...> &ruleSet, const State
556560 size_t outStateSize = 0 ;
557561 do {
558562 inStateSize = newState.size ();
563+ #ifdef TRACE_ON
564+ cout << " in size = " << inStateSize << endl;
565+ #endif
559566 newState = applyRuleSet (ruleSet, newState);
560567 outStateSize = newState.size ();
568+ #ifdef TRACE_ON
569+ cout << " out size = " << outStateSize << endl;
570+ #endif
561571 } while (inStateSize != outStateSize);
562572 return newState;
563573}
0 commit comments