souffle  2.0.2-371-g6315b36
Index.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2018, The Souffle Developers. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file Index.cpp
12  *
13  * Computes indexes for relations in a translation unit
14  *
15  ***********************************************************************/
16 
17 #include "ram/analysis/Index.h"
18 #include "Global.h"
19 #include "RelationTag.h"
20 #include "ram/Expression.h"
21 #include "ram/Node.h"
22 #include "ram/Program.h"
23 #include "ram/Relation.h"
24 #include "ram/Swap.h"
25 #include "ram/TranslationUnit.h"
26 #include "ram/analysis/Relation.h"
27 #include "ram/utility/Utils.h"
28 #include "ram/utility/Visitor.h"
30 #include <algorithm>
31 #include <cstdint>
32 #include <cstdlib>
33 #include <iostream>
34 #include <iterator>
35 #include <queue>
36 
37 namespace souffle::ram::analysis {
38 
39 SearchSignature::SearchSignature(size_t arity) : constraints(arity, AttributeConstraint::None) {}
40 
41 size_t SearchSignature::arity() const {
42  return constraints.size();
43 }
44 
45 // convenient operator overload
47  assert(pos < constraints.size());
48  return constraints[pos];
49 }
50 
51 const AttributeConstraint& SearchSignature::operator[](std::size_t pos) const {
52  assert(pos < constraints.size());
53  return constraints[pos];
54 }
55 
56 // comparison operators
57 bool SearchSignature::operator<(const SearchSignature& other) const {
58  assert(constraints.size() == other.constraints.size());
59  return isComparable(*this, other) && isSubset(*this, other);
60 }
61 
62 bool SearchSignature::operator==(const SearchSignature& other) const {
63  assert(constraints.size() == other.constraints.size());
64  return constraints == other.constraints;
65 }
66 
67 bool SearchSignature::operator!=(const SearchSignature& other) const {
68  return !(*this == other);
69 }
70 
71 bool SearchSignature::empty() const {
72  size_t len = constraints.size();
73  for (size_t i = 0; i < len; ++i) {
75  return false;
76  }
77  }
78  return true;
79 }
80 
82  for (auto constraint : constraints) {
83  if (constraint == AttributeConstraint::Equal) {
84  return true;
85  }
86  }
87  return false;
88 }
89 
90 // Note: We have 0 < 1 and 0 < 2 but we cannot say that 1 < 2.
91 // The reason for this is to prevent search chains such as 100->101->201 which have no valid lex-order
93  assert(lhs.arity() == rhs.arity());
94  if (lhs == rhs) {
95  return true;
96  }
97 
98  bool withinDelta = true;
99  for (size_t i = 0; i < rhs.arity(); ++i) {
101  if (lhs[i] != AttributeConstraint::None) {
102  withinDelta = false;
103  }
104  }
105  }
106  return withinDelta;
107 }
108 
110  assert(lhs.arity() == rhs.arity());
111  size_t len = lhs.arity();
112  for (size_t i = 0; i < len; ++i) {
114  return false;
115  }
116  }
117  return true;
118 }
119 
120 SearchSignature SearchSignature::getDelta(const SearchSignature& lhs, const SearchSignature& rhs) {
121  assert(lhs.arity() == rhs.arity());
122  SearchSignature delta(lhs.arity());
123  for (size_t i = 0; i < lhs.arity(); ++i) {
124  // if constraints are the same then delta is nothing
125  if (rhs[i] == AttributeConstraint::None) {
126  delta.constraints[i] = lhs[i];
127  } else {
128  delta.constraints[i] = AttributeConstraint::None;
129  }
130  }
131  return delta;
132 }
133 
134 SearchSignature SearchSignature::getFullSearchSignature(size_t arity) {
135  SearchSignature res(arity);
136  for (size_t i = 0; i < arity; ++i) {
137  res.constraints[i] = AttributeConstraint::Equal;
138  }
139  return res;
140 }
141 
143  SearchSignature res = signature; // copy original
144  for (size_t i = 0; i < res.arity(); ++i) {
145  if (res[i] == AttributeConstraint::Inequal) {
147  }
148  }
149  return res;
150 }
151 
152 std::ostream& operator<<(std::ostream& out, const SearchSignature& signature) {
153  size_t len = signature.constraints.size();
154  for (size_t i = 0; i < len; ++i) {
155  switch (signature.constraints[i]) {
156  case AttributeConstraint::None: out << 0; break;
157  case AttributeConstraint::Equal: out << 1; break;
158  case AttributeConstraint::Inequal: out << 2; break;
159  }
160  }
161  return out;
162 }
163 
164 void MaxMatching::addEdge(Node u, Node v) {
165  assert(u >= 1 && v >= 1 && "Nodes must be greater than or equal to 1");
166  if (graph.find(u) == graph.end()) {
167  Edges vals;
168  vals.insert(v);
169  graph.insert(make_pair(u, vals));
170  } else {
171  graph[u].insert(v);
172  }
173 }
174 
176  auto it = match.find(v);
177  if (it == match.end()) {
178  return NullVertex;
179  }
180  return it->second;
181 }
182 
184  auto it = distance.find(v);
185  if (it == distance.end()) {
186  return InfiniteDistance;
187  }
188  return it->second;
189 }
190 
191 bool MaxMatching::bfSearch() {
192  Node u;
193  std::queue<Node> bfQueue;
194  // Build layers
195  for (auto& it : graph) {
196  if (getMatch(it.first) == NullVertex) {
197  distance[it.first] = 0;
198  bfQueue.push(it.first);
199  } else {
200  distance[it.first] = InfiniteDistance;
201  }
202  }
203 
205  while (!bfQueue.empty()) {
206  u = bfQueue.front();
207  bfQueue.pop();
208  assert(u != NullVertex);
209  const Edges& children = graph[u];
210  for (auto it : children) {
211  Node mv = getMatch(it);
212  if (getDistance(mv) == InfiniteDistance) {
213  distance[mv] = getDistance(u) + 1;
214  if (mv != NullVertex) {
215  bfQueue.push(mv);
216  }
217  }
218  }
219  }
221 }
222 
223 bool MaxMatching::dfSearch(Node u) {
224  if (u != 0) {
225  Edges& children = graph[u];
226  for (auto v : children) {
227  if (getDistance(getMatch(v)) == getDistance(u) + 1) {
228  if (dfSearch(getMatch(v))) {
229  match[u] = v;
230  match[v] = u;
231  return true;
232  }
233  }
234  }
235 
237  return false;
238  }
239  return true;
240 }
241 
243  while (bfSearch()) {
244  std::vector<Node> keys(graph.size());
245  for (auto& it : graph) {
246  keys.push_back(it.first);
247  }
248  for (auto node : keys) {
249  if (getMatch(node) == NullVertex) {
250  dfSearch(node);
251  }
252  }
253  }
254  return match;
255 }
256 
258  // map the keys in the key set to lexicographical order
259  if (searches.empty()) {
260  return;
261  }
262 
263  // discharge multiple inequalities
265 
266  // map the signatures of each search to a unique index for the matching problem
267  AttributeIndex currentIndex = 1;
268  for (SearchSignature s : searches) {
269  if (s.empty()) {
270  continue;
271  }
272  // map the signature to its unique index in each set
273  signatureToIndexA.insert({s, currentIndex});
274  signatureToIndexB.insert({s, currentIndex + 1});
275  // map each index back to the search signature
276  indexToSignature.insert({currentIndex, s});
277  indexToSignature.insert({currentIndex + 1, s});
278  currentIndex += 2;
279  }
280 
281  // Construct the matching poblem
282  for (auto search : searches) {
283  for (auto itt : searches) {
284  if (search == itt) {
285  continue;
286  }
287 
288  if (search < itt) {
290  }
291  }
292  }
293 
294  // Perform the Hopcroft-Karp on the graph and receive matchings (mapped A->B and B->A)
295  // Assume: alg.calculate is not called on an empty graph
296  assert(!searches.empty());
297  const MaxMatching::Matchings& matchings = matching.solve();
298 
299  // Extract the chains given the nodes and matchings
300  ChainOrderMap chains = getChainsFromMatching(matchings, searches);
301 
302  // Should never get no chains back as we never call calculate on an empty graph
303  assert(!chains.empty());
304  for (const auto& chain : chains) {
305  std::vector<uint32_t> ids;
306 
307  SearchSignature initDelta = *(chain.begin());
308  insertIndex(ids, initDelta);
309 
310  // build the lex-order
311  for (auto iit = chain.begin(); next(iit) != chain.end(); ++iit) {
312  SearchSignature delta = SearchSignature::getDelta(*next(iit), *iit);
313  insertIndex(ids, delta);
314  }
315 
316  assert(!ids.empty());
317  orders.push_back(ids);
318  }
319 
320  // Validate the lex-order
321  for (auto chain : chains) {
322  for (auto search : chain) {
323  int idx = map(search);
324  size_t l = card(search);
325 
326  SearchSignature k(search.arity());
327  for (size_t i = 0; i < l; i++) {
329  }
330  for (size_t i = 0; i < search.arity(); ++i) {
331  if (k[i] == AttributeConstraint::None && search[i] != AttributeConstraint::None) {
332  assert("incorrect lexicographical order");
333  }
334  if (k[i] != AttributeConstraint::None && search[i] == AttributeConstraint::None) {
335  assert("incorrect lexicographical order");
336  }
337  }
338  }
339  }
340 }
341 
343  const SearchSignature umn, const MaxMatching::Matchings& match) {
344  SearchSignature start = umn; // start at an unmatched node
345  Chain chain;
346  // given an unmapped node from set A we follow it from set B until it cannot be matched from B
347  // if not mateched from B then umn is a chain
348  //
349  // Assume : no circular mappings, i.e. a in A -> b in B -> ........ -> a in A is not allowed.
350  // Given this, the loop will terminate
351  while (true) {
352  auto mit = match.find(signatureToIndexB[start]); // we start from B side
353  // on each iteration we swap sides when collecting the chain so we use the corresponding index map
354  if (std::find(chain.begin(), chain.end(), start) == chain.end()) {
355  chain.push_back(start);
356  }
357 
358  if (mit == match.end()) {
359  std::reverse(chain.begin(), chain.end());
360  return chain;
361  }
362 
363  SearchSignature a = indexToSignature.at(mit->second);
364  if (std::find(chain.begin(), chain.end(), a) == chain.end()) {
365  chain.push_back(a);
366  }
367  start = a;
368  }
369 }
370 
372  const MaxMatching::Matchings& match, const SearchSet& nodes) {
373  assert(!nodes.empty());
374 
375  // Get all unmatched nodes from A
376  const SearchSet& umKeys = getUnmatchedKeys(match, nodes);
377  // Case: if no unmatched nodes then we have an anti-chain
378  if (umKeys.empty()) {
379  for (auto node : nodes) {
380  Chain a;
381  a.push_back(node);
382  chainToOrder.push_back(a);
383  return chainToOrder;
384  }
385  }
386 
387  assert(!umKeys.empty());
388 
389  // A worklist of used nodes
390  SearchSet usedKeys;
391 
392  // Case: nodes < umKeys or if nodes == umKeys then anti chain - this is handled by this loop
393  for (auto umKey : umKeys) {
394  Chain c = getChain(umKey, match);
395  assert(!c.empty());
396  chainToOrder.push_back(c);
397  }
398 
399  assert(!chainToOrder.empty());
400  return chainToOrder;
401 }
402 
403 void MinIndexSelection::updateSearch(SearchSignature oldSearch, SearchSignature newSearch) {
404  auto delta = SearchSignature::getDelta(oldSearch, newSearch);
405  for (size_t i = 0; i < delta.arity(); ++i) {
406  if (delta[i] == AttributeConstraint::Inequal) {
407  dischargedMap[oldSearch].insert(i);
408  }
409  }
410 
411  for (auto& chain : chainToOrder) {
412  for (auto& search : chain) {
413  if (search == oldSearch) {
414  search = newSearch;
415  }
416  }
417  }
418 }
419 
421  for (auto oldSearch : searches) {
422  auto newSearch = oldSearch;
423  bool seenInequality = false;
424  for (size_t i = 0; i < oldSearch.arity(); ++i) {
425  if (oldSearch[i] == AttributeConstraint::Inequal) {
426  if (seenInequality) {
427  newSearch[i] = AttributeConstraint::None;
428  } else {
429  seenInequality = true;
430  }
431  }
432  }
433  updateSearch(oldSearch, newSearch);
434  }
435 }
436 
438  const SearchSignature& s, const Relation& rel) {
439  // by default we have all attributes w/inequalities discharged
440  AttributeSet allInequalities;
441  for (size_t i = 0; i < s.arity(); ++i) {
442  if (s[i] == AttributeConstraint::Inequal) {
443  allInequalities.insert(i);
444  }
445  }
446 
447  // if we don't have a btree then we don't retain any inequalities
448  if (rel.getRepresentation() != RelationRepresentation::BTREE &&
449  rel.getRepresentation() != RelationRepresentation::DEFAULT) {
450  return allInequalities;
451  }
452 
453  // do not support indexed inequalities with provenance
454  if (Global::config().has("provenance")) {
455  return allInequalities;
456  }
457 
458  // if we are in the interpreter then we only permit signed inequalities
459  // remembering to discharge any excess signed inequalities!
460  AttributeSet interpreterAttributesToDischarge(dischargedMap[s]);
461  for (size_t i = 0; i < s.arity(); ++i) {
462  if (s[i] == AttributeConstraint::Inequal && rel.getAttributeTypes()[i][0] != 'i') {
463  interpreterAttributesToDischarge.insert(i);
464  }
465  }
466  if (!Global::config().has("compile") && !Global::config().has("dl-program") &&
467  !Global::config().has("generate") && !Global::config().has("swig")) {
468  return interpreterAttributesToDischarge;
469  }
470 
471  return dischargedMap[s];
472 }
473 
474 void IndexAnalysis::run(const TranslationUnit& translationUnit) {
475  relAnalysis = translationUnit.getAnalysis<RelationAnalysis>();
476 
477  // After complete:
478  // 1. All relations should have at least one index (for full-order search).
479  // 2. Two relations involved in a swap operation will have same set of indices.
480  // 3. A 0-arity relation will have only one index where LexOrder is defined as empty. A comparator using
481  // an empty order should regard all elements as equal and therefore only allow one arbitrary tuple to be
482  // inserted.
483  //
484  // TODO:
485  // 0-arity relation in a provenance program still need to be revisited.
486  // visit all nodes to collect searches of each relation
487 
488  // visit all nodes to collect searches of each relation
489  visitDepthFirst(translationUnit.getProgram(), [&](const Node& node) {
490  if (const auto* indexSearch = dynamic_cast<const IndexOperation*>(&node)) {
491  MinIndexSelection& indexes = getIndexes(indexSearch->getRelation());
492  indexes.addSearch(getSearchSignature(indexSearch));
493  } else if (const auto* exists = dynamic_cast<const ExistenceCheck*>(&node)) {
494  MinIndexSelection& indexes = getIndexes(exists->getRelation());
495  indexes.addSearch(getSearchSignature(exists));
496  } else if (const auto* provExists = dynamic_cast<const ProvenanceExistenceCheck*>(&node)) {
497  MinIndexSelection& indexes = getIndexes(provExists->getRelation());
498  indexes.addSearch(getSearchSignature(provExists));
499  } else if (const auto* ramRel = dynamic_cast<const Relation*>(&node)) {
500  MinIndexSelection& indexes = getIndexes(ramRel->getName());
501  indexes.addSearch(getSearchSignature(ramRel));
502  }
503  });
504 
505  // A swap happen between rel A and rel B indicates A should include all indices of B, vice versa.
506  visitDepthFirst(translationUnit.getProgram(), [&](const Swap& swap) {
507  // Note: this naive approach will not work if there exists chain or cyclic swapping.
508  // e.g. swap(relA, relB) swap(relB, relC) swap(relC, relA)
509  // One need to keep merging the search set until a fixed point where no more index is introduced
510  // in any of the relation in a complete iteration.
511  //
512  // Currently RAM does not have such situation.
513  const std::string& relA = swap.getFirstRelation();
514  const std::string& relB = swap.getSecondRelation();
515  MinIndexSelection& indexesA = getIndexes(relA);
516  MinIndexSelection& indexesB = getIndexes(relB);
517  // Add all searchSignature of A into B
518  for (const auto& signature : indexesA.getSearches()) {
519  indexesB.addSearch(signature);
520  }
521 
522  // Add all searchSignature of B into A
523  for (const auto& signature : indexesB.getSearches()) {
524  indexesA.addSearch(signature);
525  }
526  });
527 
528  // find optimal indexes for relations
529  for (auto& cur : minIndexCover) {
530  MinIndexSelection& indexes = cur.second;
531  indexes.solve();
532  }
533 
534  // Only case where indexSet is still empty is when relation has arity == 0
535  for (auto& cur : minIndexCover) {
536  MinIndexSelection& indexes = cur.second;
537  if (indexes.getAllOrders().empty()) {
538  indexes.insertDefaultTotalIndex(0);
539  }
540  }
541 }
542 
543 MinIndexSelection& IndexAnalysis::getIndexes(const std::string& relName) {
544  auto pos = minIndexCover.find(relName);
545  if (pos != minIndexCover.end()) {
546  return pos->second;
547  } else {
548  auto ret = minIndexCover.insert(std::make_pair(relName, MinIndexSelection()));
549  assert(ret.second);
550  return ret.first->second;
551  }
552 }
553 
554 void IndexAnalysis::print(std::ostream& os) const {
555  for (auto& cur : minIndexCover) {
556  const std::string& relName = cur.first;
557  const MinIndexSelection& indexes = cur.second;
558 
559  /* Print searches */
560  os << "Relation " << relName << "\n";
561  os << "\tNumber of Searches: " << indexes.getSearches().size() << "\n";
562 
563  /* print searches */
564  for (auto& search : indexes.getSearches()) {
565  os << "\t\t";
566  os << search;
567  os << "\n";
568  }
569 
570  /* print chains */
571  for (auto& chain : indexes.getAllChains()) {
572  os << join(chain, "-->") << "\n";
573  }
574  os << "\n";
575 
576  os << "\tNumber of Indexes: " << indexes.getAllOrders().size() << "\n";
577  for (auto& order : indexes.getAllOrders()) {
578  os << "\t\t";
579  os << join(order, "<") << "\n";
580  os << "\n";
581  }
582  }
583 }
584 
585 namespace {
586 // handles equality constraints
587 template <typename Iter>
588 SearchSignature searchSignature(size_t arity, Iter const& bgn, Iter const& end) {
589  SearchSignature keys(arity);
590 
591  size_t i = 0;
592  for (auto cur = bgn; cur != end; ++cur, ++i) {
593  if (!isUndefValue(*cur)) {
595  }
596  }
597  return keys;
598 }
599 
600 template <typename Seq>
601 SearchSignature searchSignature(size_t arity, Seq const& xs) {
602  return searchSignature(arity, xs.begin(), xs.end());
603 }
604 } // namespace
605 
606 SearchSignature IndexAnalysis::getSearchSignature(const IndexOperation* search) const {
607  const Relation* rel = &relAnalysis->lookup(search->getRelation());
608  size_t arity = rel->getArity();
609 
610  auto lower = search->getRangePattern().first;
611  auto upper = search->getRangePattern().second;
612  SearchSignature keys(arity);
613  for (size_t i = 0; i < arity; ++i) {
614  // if both bounds are undefined
615  if (isUndefValue(lower[i]) && isUndefValue(upper[i])) {
617  // if bounds are equal we have an equality
618  } else if (*lower[i] == *upper[i]) {
620  } else {
622  }
623  }
624  return keys;
625 }
626 
627 SearchSignature IndexAnalysis::getSearchSignature(const ProvenanceExistenceCheck* provExistCheck) const {
628  const auto values = provExistCheck->getValues();
629  const Relation* rel = &relAnalysis->lookup(provExistCheck->getRelation());
630  auto auxiliaryArity = rel->getAuxiliaryArity();
631 
632  SearchSignature keys(values.size());
633 
634  // all payload attributes should be equalities
635  for (size_t i = 0; i < values.size() - auxiliaryArity; i++) {
636  if (!isUndefValue(values[i])) {
638  }
639  }
640 
641  // all auxiliary attributes should be free
642  for (size_t i = values.size() - auxiliaryArity; i < values.size(); i++) {
644  }
645 
646  return keys;
647 }
648 
649 SearchSignature IndexAnalysis::getSearchSignature(const ExistenceCheck* existCheck) const {
650  const Relation* rel = &relAnalysis->lookup(existCheck->getRelation());
651  return searchSignature(rel->getArity(), existCheck->getValues());
652 }
653 
654 SearchSignature IndexAnalysis::getSearchSignature(const Relation* ramRel) const {
655  return SearchSignature::getFullSearchSignature(ramRel->getArity());
656 }
657 
658 bool IndexAnalysis::isTotalSignature(const AbstractExistenceCheck* existCheck) const {
659  for (const auto& cur : existCheck->getValues()) {
660  if (isUndefValue(cur)) {
661  return false;
662  }
663  }
664  return true;
665 }
666 
667 } // namespace souffle::ram::analysis
souffle::ram::analysis::MaxMatching::solve
const Matchings & solve()
@Brief solve the maximum matching problem
Definition: Index.cpp:248
souffle::ram::analysis::SearchSignature
search signature of a RAM operation; each bit represents an attribute of a relation.
Definition: Index.h:52
souffle::ram::analysis::MaxMatching::getDistance
Distance getDistance(Node v)
@Brief get distance of a node
Definition: Index.cpp:189
souffle::ram::analysis::SearchSignature::SearchSignature
SearchSignature(size_t arity)
Definition: Index.cpp:45
souffle::ram::analysis::MaxMatching::NullVertex
const Node NullVertex
Definition: Index.h:127
souffle::ram::AbstractExistenceCheck::getValues
const std::vector< Expression * > getValues() const
Get arguments of the tuple/pattern A null pointer element in the vector denotes an unspecified patter...
Definition: AbstractExistenceCheck.h:66
souffle::ram::analysis::AttributeConstraint
AttributeConstraint
Definition: Index.h:47
souffle::ram::analysis::MinIndexSelection::orders
OrderCollection orders
Definition: Index.h:333
Index.h
souffle::ram::analysis::MinIndexSelection::matching
MaxMatching matching
Definition: Index.h:335
souffle::ram::analysis::MinIndexSelection::Chain
std::vector< SearchSignature > Chain
Definition: Index.h:218
souffle::ram::isUndefValue
bool isUndefValue(const Expression *expr)
Determines if an expression represents an undefined value.
Definition: Utils.h:40
souffle::ram::analysis::operator<<
std::ostream & operator<<(std::ostream &out, const SearchSignature &signature)
Definition: Index.cpp:158
souffle::ram::analysis::MinIndexSelection::searches
SearchSet searches
Definition: Index.h:332
souffle::ram::analysis::MaxMatching::getMatch
Node getMatch(Node v)
@Brief get match for a search signature
Definition: Index.cpp:181
souffle::ram::analysis::MinIndexSelection::getUnmatchedKeys
const SearchSet getUnmatchedKeys(const MaxMatching::Matchings &match, const SearchSet &nodes)
@Brief get all nodes which are unmatched from A-> B
Definition: Index.h:396
souffle::ram::analysis::MinIndexSelection::insertIndex
void insertIndex(LexOrder &ids, SearchSignature delta)
@Brief insert an index based on the delta
Definition: Index.h:362
souffle::ram::analysis
Definition: Analysis.h:32
souffle::ram::analysis::AttributeConstraint::Inequal
@ Inequal
souffle::ram::analysis::MinIndexSelection::updateSearch
void updateSearch(SearchSignature oldSearch, SearchSignature newSearch)
Definition: Index.cpp:409
souffle::ram::analysis::IndexAnalysis::print
void print(std::ostream &os) const override
Print the analysis result in HTML format.
Definition: Index.cpp:560
souffle::ram::analysis::MaxMatching::InfiniteDistance
const Distance InfiniteDistance
Definition: Index.h:130
Swap.h
souffle::ram::ExistenceCheck
Existence check for a tuple(-pattern) in a relation.
Definition: ExistenceCheck.h:49
souffle::ram::analysis::MinIndexSelection::map
int map(SearchSignature cols) const
@Brief maps search columns to an lexicographical order (labeled by a number)
Definition: Index.h:349
rhs
Own< Argument > rhs
Definition: ResolveAliases.cpp:185
souffle::ram::analysis::IndexAnalysis::minIndexCover
std::map< std::string, MinIndexSelection > minIndexCover
minimal index cover for relations, i.e., maps a relation to a set of indexes
Definition: Index.h:474
souffle::ram::analysis::MinIndexSelection::SearchSet
std::set< SearchSignature, SearchComparator > SearchSet
Definition: Index.h:231
souffle::ram::analysis::SearchSignature::arity
size_t arity() const
Definition: Index.cpp:47
souffle::ram::analysis::MaxMatching::Matchings
std::unordered_map< Node, Node > Matchings
Matching represent a solution of the matching, i.e., which node in the bi-partite graph maps to anoth...
Definition: Index.h:124
souffle::ram::analysis::SearchSignature::getDischarged
static SearchSignature getDischarged(const SearchSignature &signature)
Definition: Index.cpp:148
souffle::ram::analysis::MinIndexSelection::AttributeSet
std::unordered_set< AttributeIndex > AttributeSet
Definition: Index.h:211
Program.h
souffle::ram::analysis::MaxMatching::bfSearch
bool bfSearch()
@Brief perform a breadth first search in the graph
Definition: Index.cpp:197
souffle::ram::analysis::AttributeConstraint::None
@ None
Global.h
souffle::ram::analysis::IndexAnalysis::run
void run(const TranslationUnit &translationUnit) override
Run analysis for a RAM translation unit.
Definition: Index.cpp:480
lhs
Own< Argument > lhs
Definition: ResolveAliases.cpp:184
souffle::ram::ProvenanceExistenceCheck
Provenance Existence check for a relation.
Definition: ProvenanceExistenceCheck.h:42
souffle::Relation
Object-oriented wrapper class for Souffle's templatized relations.
Definition: SouffleInterface.h:49
l
var l
Definition: htmlJsChartistMin.h:15
souffle::ram::Node
Node is a superclass for all RAM IR classes.
Definition: Node.h:42
Relation.h
souffle::ram::analysis::SearchSignature::constraints
std::vector< AttributeConstraint > constraints
Definition: Index.h:90
Visitor.h
souffle::ram::analysis::MaxMatching::graph
Graph graph
Definition: Index.h:191
souffle::ram::analysis::SearchSignature::operator!=
bool operator!=(const SearchSignature &other) const
Definition: Index.cpp:73
i
size_t i
Definition: json11.h:663
souffle::ram::analysis::MinIndexSelection::removeExtraInequalities
void removeExtraInequalities()
@Brief remove arbitrary extra inequalities
Definition: Index.cpp:426
souffle::ram::analysis::MaxMatching::Distance
int Distance
Definition: Index.h:118
souffle::ram::analysis::SearchSignature::operator[]
AttributeConstraint & operator[](std::size_t pos)
Definition: Index.cpp:52
souffle::ram::analysis::MinIndexSelection::ChainOrderMap
std::list< Chain > ChainOrderMap
Definition: Index.h:221
RelationTag.h
souffle::ram::Relation
An abstract class for performing indexed operations.
Definition: Relation.h:40
Relation.h
souffle::ram::analysis::MinIndexSelection::getAllChains
const ChainOrderMap getAllChains() const
@Brief Get all chains
Definition: Index.h:268
souffle::join
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
Definition: StreamUtil.h:175
souffle::ram::analysis::SearchSignature::isSubset
static bool isSubset(const SearchSignature &lhs, const SearchSignature &rhs)
Definition: Index.cpp:115
souffle::ram::AbstractExistenceCheck
Abstract existence check for a tuple in a relation.
Definition: AbstractExistenceCheck.h:47
souffle::ram::analysis::MinIndexSelection
Definition: Index.h:208
souffle::ram::analysis::SearchSignature::isComparable
static bool isComparable(const SearchSignature &lhs, const SearchSignature &rhs)
Definition: Index.cpp:98
souffle::ram::analysis::MinIndexSelection::getChainsFromMatching
const ChainOrderMap getChainsFromMatching(const MaxMatching::Matchings &match, const SearchSet &nodes)
@Brief get all chains from the matching
Definition: Index.cpp:377
souffle::ram::analysis::MinIndexSelection::indexToSignature
IndexSignatureMap indexToSignature
Definition: Index.h:331
Utils.h
souffle::ram::analysis::MinIndexSelection::card
static size_t card(SearchSignature cols)
@Brief count the number of constraints in key
Definition: Index.h:338
souffle::ram::analysis::MinIndexSelection::dischargedMap
DischargeMap dischargedMap
Definition: Index.h:330
souffle::ram::analysis::MinIndexSelection::chainToOrder
ChainOrderMap chainToOrder
Definition: Index.h:334
souffle::ram::analysis::MinIndexSelection::AttributeIndex
uint32_t AttributeIndex
Definition: Index.h:210
souffle::ram::analysis::IndexAnalysis::isTotalSignature
bool isTotalSignature(const AbstractExistenceCheck *existCheck) const
@Brief index signature of existence check resembles a total index
Definition: Index.cpp:664
TranslationUnit.h
k
var k
Definition: htmlJsChartistMin.h:15
souffle::ram::analysis::MinIndexSelection::signatureToIndexB
SignatureIndexMap signatureToIndexB
Definition: Index.h:329
souffle::ram::analysis::MinIndexSelection::signatureToIndexA
SignatureIndexMap signatureToIndexA
Definition: Index.h:328
souffle::ram::analysis::SearchSignature::getFullSearchSignature
static SearchSignature getFullSearchSignature(size_t arity)
Definition: Index.cpp:140
souffle::ram::analysis::MinIndexSelection::solve
void solve()
@Brief map the keys in the key set to lexicographical order
Definition: Index.cpp:263
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
souffle::ram::analysis::SearchSignature::operator==
bool operator==(const SearchSignature &other) const
Definition: Index.cpp:68
Node.h
souffle::ram::analysis::AttributeConstraint::Equal
@ Equal
souffle::RelationRepresentation::DEFAULT
@ DEFAULT
souffle::ram::analysis::MinIndexSelection::getAttributesToDischarge
AttributeSet getAttributesToDischarge(const SearchSignature &s, const Relation &rel)
Return the attribute position for each indexed operation that should be discharged.
Definition: Index.cpp:443
souffle::ram::analysis::IndexAnalysis::relAnalysis
RelationAnalysis * relAnalysis
relation analysis for looking up relations by name
Definition: Index.h:469
souffle::ram::analysis::SearchSignature::operator<
bool operator<(const SearchSignature &other) const
Definition: Index.cpp:63
souffle::ram::analysis::MinIndexSelection::addSearch
void addSearch(SearchSignature cols)
@Brief Add new key to an Index Set
Definition: Index.h:237
souffle::ram::analysis::SearchSignature::containsEquality
bool containsEquality() const
Definition: Index.cpp:87
souffle::ram::analysis::SearchSignature::getDelta
static SearchSignature getDelta(const SearchSignature &lhs, const SearchSignature &rhs)
Definition: Index.cpp:126
StreamUtil.h
souffle::ram::analysis::MaxMatching::distance
DistanceMap distance
Definition: Index.h:192
souffle::ram::analysis::MaxMatching::Node
uint32_t Node
Definition: Index.h:114
souffle::ram::analysis::MinIndexSelection::getAllOrders
const OrderCollection getAllOrders() const
@Brief Get all indexes
Definition: Index.h:263
souffle::ram::analysis::MaxMatching::addEdge
void addEdge(Node u, Node v)
@Brief add an edge to the bi-partite graph
Definition: Index.cpp:170
Expression.h
souffle::RelationRepresentation::BTREE
@ BTREE
souffle::ram::analysis::MinIndexSelection::getSearches
const SearchSet & getSearches() const
@Brief Get searches
Definition: Index.h:247
souffle::ram::analysis::RelationAnalysis::lookup
const ram::Relation & lookup(const std::string &name) const
Definition: Relation.cpp:33
souffle::ram::analysis::IndexAnalysis::getIndexes
MinIndexSelection & getIndexes(const std::string &relName)
@Brief get the minimal index cover for a relation
Definition: Index.cpp:549
souffle::ram::analysis::IndexAnalysis::getSearchSignature
SearchSignature getSearchSignature(const IndexOperation *search) const
@Brief Get index signature for an Ram IndexOperation operation
Definition: Index.cpp:612
souffle::ram::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the RAM fragments rooted by the given node recursively i...
Definition: Visitor.h:357
souffle::ram::analysis::MinIndexSelection::getChain
Chain getChain(const SearchSignature umn, const MaxMatching::Matchings &match)
@Brief get a chain from a matching
Definition: Index.cpp:348
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::ram::analysis::SearchSignature::empty
bool empty() const
Definition: Index.cpp:77
souffle::ram::analysis::MaxMatching::match
Matchings match
Definition: Index.h:190
souffle::ram::analysis::MaxMatching::dfSearch
bool dfSearch(Node u)
@Brief perform a depth first search in the graph
Definition: Index.cpp:229
souffle::ram::analysis::MaxMatching::Edges
std::unordered_set< Node > Edges
Edges in the bi-partite graph.
Definition: Index.h:180