Skip to content

Commit

Permalink
Merge pull request souffle-lang#1785 from SamArch27/index-analysis-re…
Browse files Browse the repository at this point in the history
…factor

Index analysis refactor #2
  • Loading branch information
Bernhard Scholz authored Dec 6, 2020
2 parents c07b5dc + a08a1c1 commit 42e99c3
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 457 deletions.
2 changes: 0 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,6 @@ souffle_sources = \
ram/transform/HoistConditions.h \
ram/transform/IfConversion.cpp \
ram/transform/IfConversion.h \
ram/transform/IndexedInequality.cpp \
ram/transform/IndexedInequality.h \
ram/transform/Loop.h \
ram/transform/MakeIndex.cpp \
ram/transform/MakeIndex.h \
Expand Down
19 changes: 19 additions & 0 deletions src/include/souffle/BinaryConstraintOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,25 @@ inline bool isWeakIneqConstraint(const BinaryConstraintOp constraintOp) {
return false;
}

inline bool isIneqConstraint(const BinaryConstraintOp constraintOp) {
return isStrictIneqConstraint(constraintOp) || isWeakIneqConstraint(constraintOp);
}

inline bool isIndexableConstraint(const BinaryConstraintOp constraintOp) {
return isIneqConstraint(constraintOp) || isEqConstraint(constraintOp);
}

inline bool isSignedInequalityConstraint(const BinaryConstraintOp constraintOp) {
switch (constraintOp) {
case BinaryConstraintOp::LE:
case BinaryConstraintOp::GE:
case BinaryConstraintOp::LT:
case BinaryConstraintOp::GT: return true;
default: break;
}
return false;
}

inline BinaryConstraintOp convertStrictToWeakIneqConstraint(const BinaryConstraintOp constraintOp) {
assert(isStrictIneqConstraint(constraintOp));
switch (constraintOp) {
Expand Down
5 changes: 2 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
#include "ram/transform/HoistAggregate.h"
#include "ram/transform/HoistConditions.h"
#include "ram/transform/IfConversion.h"
#include "ram/transform/IndexedInequality.h"
#include "ram/transform/Loop.h"
#include "ram/transform/MakeIndex.h"
#include "ram/transform/Parallel.h"
Expand Down Expand Up @@ -595,8 +594,8 @@ int main(int argc, char** argv) {
Own<Transformer> ramTransform = mk<TransformerSequence>(
mk<LoopTransformer>(mk<TransformerSequence>(mk<ExpandFilterTransformer>(),
mk<HoistConditionsTransformer>(), mk<MakeIndexTransformer>())),
mk<LoopTransformer>(mk<IndexedInequalityTransformer>()), mk<IfConversionTransformer>(),
mk<ChoiceConversionTransformer>(), mk<CollapseFiltersTransformer>(), mk<TupleIdTransformer>(),
mk<IfConversionTransformer>(), mk<ChoiceConversionTransformer>(),
mk<CollapseFiltersTransformer>(), mk<TupleIdTransformer>(),
mk<LoopTransformer>(
mk<TransformerSequence>(mk<HoistAggregateTransformer>(), mk<TupleIdTransformer>())),
mk<ExpandFilterTransformer>(), mk<HoistConditionsTransformer>(),
Expand Down
119 changes: 18 additions & 101 deletions src/ram/analysis/Index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,20 @@ namespace souffle::ram::analysis {

SearchSignature::SearchSignature(size_t arity) : constraints(arity, AttributeConstraint::None) {}

size_t SearchSignature::arity() const {
return constraints.size();
bool SearchSignature::operator==(const SearchSignature& other) const {
assert(constraints.size() == other.constraints.size());
return constraints == other.constraints;
}

bool SearchSignature::operator!=(const SearchSignature& other) const {
return !(*this == other);
}

bool SearchSignature::empty() const {
return std::all_of(constraints.begin(), constraints.end(),
[](AttributeConstraint c) { return c == AttributeConstraint::None; });
}

// convenient operator overload
AttributeConstraint& SearchSignature::operator[](std::size_t pos) {
assert(pos < constraints.size());
return constraints[pos];
Expand All @@ -53,8 +62,12 @@ const AttributeConstraint& SearchSignature::operator[](std::size_t pos) const {
return constraints[pos];
}

size_t SearchSignature::arity() const {
return constraints.size();
}

// comparison operators
bool SearchSignature::operator<(const SearchSignature& other) const {
bool SearchSignature::precedes(const SearchSignature& other) const {
assert(arity() == other.arity());
// ignore duplicates
if (*this == other) {
Expand All @@ -80,21 +93,6 @@ bool SearchSignature::operator<(const SearchSignature& other) const {
}
return true;
}

bool SearchSignature::operator==(const SearchSignature& other) const {
assert(constraints.size() == other.constraints.size());
return constraints == other.constraints;
}

bool SearchSignature::operator!=(const SearchSignature& other) const {
return !(*this == other);
}

bool SearchSignature::empty() const {
return std::all_of(constraints.begin(), constraints.end(),
[](AttributeConstraint c) { return c == AttributeConstraint::None; });
}

SearchSignature SearchSignature::getDelta(const SearchSignature& lhs, const SearchSignature& rhs) {
assert(lhs.arity() == rhs.arity());
SearchSignature delta(lhs.arity());
Expand Down Expand Up @@ -227,9 +225,6 @@ void MinIndexSelection::solve() {
return;
}

// discharge multiple inequalities
removeExtraInequalities();

// map the signatures of each search to a unique index for the matching problem
AttributeIndex currentIndex = 1;
for (auto s : searches) {
Expand All @@ -247,7 +242,7 @@ void MinIndexSelection::solve() {
// Draw an edge from LHS to RHS if LHS precedes RHS in the partial order
for (auto left : searches) {
for (auto right : searches) {
if (left < right) {
if (left.precedes(right)) {
matching.addEdge(signatureToIndexA[left], signatureToIndexB[right]);
}
}
Expand Down Expand Up @@ -360,84 +355,6 @@ const ChainOrderMap MinIndexSelection::getChainsFromMatching(
return chainToOrder;
}

void MinIndexSelection::updateSearch(SearchSignature oldSearch, SearchSignature newSearch) {
auto delta = SearchSignature::getDelta(oldSearch, newSearch);
for (size_t i = 0; i < delta.arity(); ++i) {
if (delta[i] == AttributeConstraint::Inequal) {
dischargedMap[oldSearch].insert(i);
}
}

for (auto& chain : chainToOrder) {
for (auto& search : chain) {
if (search == oldSearch) {
search = newSearch;
}
}
}
}

void MinIndexSelection::removeExtraInequalities() {
for (auto oldSearch : searches) {
auto newSearch = oldSearch;

// find the first inequality (if it exists)
auto it = std::find(newSearch.begin(), newSearch.end(), AttributeConstraint::Inequal);
// remove all inequalities
std::for_each(newSearch.begin(), newSearch.end(), [](auto& constraint) {
if (constraint == AttributeConstraint::Inequal) {
constraint = AttributeConstraint::None;
}
});
// add back the first inequality (if it exists)
if (it != newSearch.end()) {
auto index = std::distance(newSearch.begin(), it);
newSearch[index] = AttributeConstraint::Inequal;
}
updateSearch(oldSearch, newSearch);
}
}

const AttributeSet MinIndexSelection::getAttributesToDischarge(
const Relation& rel, const SearchSignature& s) const {
auto dischargedAttributes = dischargedMap.count(s) > 0 ? dischargedMap.at(s) : AttributeSet{};

// by default we have all attributes w/inequalities discharged
AttributeSet allInequalities;
for (size_t i = 0; i < s.arity(); ++i) {
if (s[i] == AttributeConstraint::Inequal) {
allInequalities.insert(i);
}
}

// if we don't have a btree then we don't retain any inequalities
if (rel.getRepresentation() != RelationRepresentation::BTREE &&
rel.getRepresentation() != RelationRepresentation::DEFAULT) {
return allInequalities;
}

// do not support indexed inequalities with provenance
if (Global::config().has("provenance")) {
return allInequalities;
}

// if we are in the interpreter then we only permit signed inequalities
// remembering to discharge any excess signed inequalities!
AttributeSet interpreterAttributesToDischarge = dischargedAttributes;

for (size_t i = 0; i < s.arity(); ++i) {
if (s[i] == AttributeConstraint::Inequal && rel.getAttributeTypes()[i][0] != 'i') {
interpreterAttributesToDischarge.insert(i);
}
}
if (!Global::config().has("compile") && !Global::config().has("dl-program") &&
!Global::config().has("generate") && !Global::config().has("swig")) {
return interpreterAttributesToDischarge;
}

return dischargedAttributes;
}

void IndexAnalysis::run(const TranslationUnit& translationUnit) {
relAnalysis = translationUnit.getAnalysis<RelationAnalysis>();

Expand Down
33 changes: 8 additions & 25 deletions src/ram/analysis/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,27 @@ enum class AttributeConstraint { None, Equal, Inequal };
class SearchSignature {
public:
class Iterator;

explicit SearchSignature(size_t arity);
size_t arity() const;

// array subscript operator
AttributeConstraint& operator[](std::size_t pos);
const AttributeConstraint& operator[](std::size_t pos) const;

// comparison operators
bool operator<(const SearchSignature& other) const;
bool operator==(const SearchSignature& other) const;
bool operator!=(const SearchSignature& other) const;

// helper member functions
bool empty() const;
bool precedes(const SearchSignature& other) const;
size_t arity() const;

// create new signatures from these functions
static SearchSignature getDelta(const SearchSignature& lhs, const SearchSignature& rhs);
static SearchSignature getFullSearchSignature(size_t arity);

// printing
friend std::ostream& operator<<(std::ostream& out, const SearchSignature& signature);

// hashing class
Expand Down Expand Up @@ -319,8 +323,8 @@ class SearchComparator {

using SearchSet = std::set<SearchSignature, SearchComparator>;
// SearchSignatures only have a partial order, however we need to produce a unique ordering of searches
// when we output the name of the index and therefore we order the SearchSignatures arbitrarily by their
// hashes
// when we output the name of the collection of searches and therefore we order the SearchSignatures
// arbitrarily by their hashes

class MinIndexSelection {
public:
Expand All @@ -347,11 +351,6 @@ class MinIndexSelection {
return orders[idx];
}

/** @Brief Get index for a search */
int getLexOrderNum(SearchSignature cols) const {
return map(cols);
}

/** @Brief Get all indexes */
const OrderCollection getAllOrders() const {
return orders;
Expand Down Expand Up @@ -388,9 +387,6 @@ class MinIndexSelection {
}
orders.push_back(std::move(totalOrder));
}
/** Return the attribute position for each indexed operation that should be discharged.
*/
const AttributeSet getAttributesToDischarge(const Relation& rel, const SearchSignature& s) const;

void print(std::ostream& os) {
/* Print searches */
Expand Down Expand Up @@ -420,7 +416,6 @@ class MinIndexSelection {
protected:
SignatureIndexMap signatureToIndexA; // mapping of a SearchSignature on A to its unique index
SignatureIndexMap signatureToIndexB; // mapping of a SearchSignature on B to its unique index
DischargeMap dischargedMap; // mapping of a SearchSignature to the attributes to discharge
IndexSignatureMap indexToSignature; // mapping of a unique index to its SearchSignature
SearchSet searches; // set of search patterns on table
OrderCollection orders; // collection of lexicographical orders
Expand Down Expand Up @@ -477,14 +472,6 @@ class MinIndexSelection {
/** @Brief get all chains from the matching */
const ChainOrderMap getChainsFromMatching(const MaxMatching::Matchings& match, const SearchSet& nodes);

/** @param OldSearch to be updated
* @param NewSearch to replace the OldSearch
*/
void updateSearch(SearchSignature oldSearch, SearchSignature newSearch);

/** @Brief remove arbitrary extra inequalities */
void removeExtraInequalities();

/** @Brief get all nodes which are unmatched from A-> B */
const SearchSet getUnmatchedKeys(const MaxMatching::Matchings& match, const SearchSet& nodes) {
SearchSet unmatched;
Expand Down Expand Up @@ -547,10 +534,6 @@ class IndexAnalysis : public Analysis {

void run(const TranslationUnit& translationUnit) override;

const AttributeSet getAttributesToDischarge(const Relation& rel, const SearchSignature& s) const {
return minIndexCover.at(rel.getName()).getAttributesToDischarge(rel, s);
}

const FinalIndexSelection getIndexSelection(const std::string& relName) const {
SignatureOrderMap indexSelection = {};
const auto& cover = minIndexCover.at(relName);
Expand Down
Loading

0 comments on commit 42e99c3

Please sign in to comment.