souffle  2.0.2-371-g6315b36
Public Member Functions | Private Types | Private Member Functions | Private Attributes
souffle::ExplainProvenanceImpl Class Reference

#include <ExplainProvenanceImpl.h>

Inheritance diagram for souffle::ExplainProvenanceImpl:
Inheritance graph
Collaboration diagram for souffle::ExplainProvenanceImpl:
Collaboration graph

Public Member Functions

Own< TreeNodeexplain (std::string relName, std::vector< RamDomain > tuple, int ruleNum, int levelNum, size_t depthLimit)
 
Own< TreeNodeexplain (std::string relName, std::vector< std::string > args, size_t depthLimit) override
 
Own< TreeNodeexplainNegation (std::string relName, size_t ruleNum, const std::vector< std::string > &tuple, std::map< std::string, std::string > &bodyVariables) override
 
std::vector< std::string > explainNegationGetVariables (std::string relName, std::vector< std::string > args, size_t ruleNum) override
 
 ExplainProvenanceImpl (SouffleProgram &prog)
 
Own< TreeNodeexplainSubproof (std::string relName, RamDomain subproofNum, size_t depthLimit) override
 
std::string getRule (std::string relName, size_t ruleNum) override
 
std::vector< std::string > getRules (const std::string &relName) override
 
std::string measureRelation (std::string relName) override
 
void printRulesJSON (std::ostream &os) override
 
void queryProcess (const std::vector< std::pair< std::string, std::vector< std::string >>> &rels) override
 Process query with given arguments. More...
 
void setup () override
 
- Public Member Functions inherited from souffle::ExplainProvenance
 ExplainProvenance (SouffleProgram &prog)
 
virtual ~ExplainProvenance ()=default
 

Private Types

using arity_type = Relation::arity_type
 

Private Member Functions

bool containsTuple (Relation *relation, const std::vector< RamDomain > &constTuple)
 
void findQuerySolution (const std::vector< Relation * > &varRels, const std::map< std::string, Equivalence > &nameToEquivalence, const ConstConstraint &constConstraints)
 
std::tuple< int, int > findTuple (const std::string &relName, std::vector< RamDomain > tup)
 

Private Attributes

std::vector< std::string > constraintList
 
std::map< std::pair< std::string, size_t >, std::vector< std::string > > info
 
std::map< std::pair< std::string, size_t >, std::string > rules
 
std::vector< std::vector< RamDomain > > subproofs
 

Additional Inherited Members

- Protected Member Functions inherited from souffle::ExplainProvenance
std::vector< RamDomainargsToNums (const std::string &relName, const std::vector< std::string > &args) const
 
std::vector< std::string > decodeArguments (const std::string &relName, const std::vector< RamDomain > &nums) const
 Decode arguments from their ram representation and return as strings. More...
 
RamDomain valueRead (const char type, const std::string &value) const
 
std::string valueShow (const char type, const RamDomain value) const
 
- Protected Attributes inherited from souffle::ExplainProvenance
SouffleProgramprog
 
SymbolTablesymTable
 

Detailed Description

Definition at line 54 of file ExplainProvenanceImpl.h.

Member Typedef Documentation

◆ arity_type

Definition at line 55 of file ExplainProvenanceImpl.h.

Constructor & Destructor Documentation

◆ ExplainProvenanceImpl()

souffle::ExplainProvenanceImpl::ExplainProvenanceImpl ( SouffleProgram prog)
inline

Definition at line 58 of file ExplainProvenanceImpl.h.

58  : prog.getAllRelations()) {
59  std::string name = rel->getName();
60 

References rel().

Here is the call graph for this function:

Member Function Documentation

◆ containsTuple()

bool souffle::ExplainProvenanceImpl::containsTuple ( Relation relation,
const std::vector< RamDomain > &  constTuple 
)
inlineprivate

Definition at line 894 of file ExplainProvenanceImpl.h.

898  {
899  tupleExist = true;
900  break;
901  }
902  }
903  return tupleExist;
904  }
905 };
906 
907 } // end of namespace souffle

◆ explain() [1/2]

Own<TreeNode> souffle::ExplainProvenanceImpl::explain ( std::string  relName,
std::vector< RamDomain tuple,
int  ruleNum,
int  levelNum,
size_t  depthLimit 
)
inline

Definition at line 94 of file ExplainProvenanceImpl.h.

95  {
96  return mk<LeafNode>(relName + "(" + joinedArgsStr + ")");
97  }
98 
99  assert(info.find(std::make_pair(relName, ruleNum)) != info.end() && "invalid rule for tuple");
100 
101  // if depth limit exceeded
102  if (depthLimit <= 1) {
103  tuple.push_back(ruleNum);
104  tuple.push_back(levelNum);
105 
106  // find if subproof exists already
107  size_t idx = 0;
108  auto it = std::find(subproofs.begin(), subproofs.end(), tuple);
109  if (it != subproofs.end()) {
110  idx = it - subproofs.begin();
111  } else {
112  subproofs.push_back(tuple);
113  idx = subproofs.size() - 1;
114  }
115 
116  return mk<LeafNode>("subproof " + relName + "(" + std::to_string(idx) + ")");
117  }
118 
119  tuple.push_back(levelNum);
120 
121  auto internalNode =
122  mk<InnerNode>(relName + "(" + joinedArgsStr + ")", "(R" + std::to_string(ruleNum) + ")");
123 
124  // make return vector pointer
125  std::vector<RamDomain> ret;
126 
127  // execute subroutine to get subproofs
128  prog.executeSubroutine(relName + "_" + std::to_string(ruleNum) + "_subproof", tuple, ret);
129 
130  // recursively get nodes for subproofs
131  size_t tupleCurInd = 0;
132  auto bodyRelations = info[std::make_pair(relName, ruleNum)];
133 
134  // start from begin + 1 because the first element represents the head atom
135  for (auto it = bodyRelations.begin() + 1; it < bodyRelations.end(); it++) {
136  std::string bodyLiteral = *it;
137  // split bodyLiteral since it contains relation name plus arguments
138  std::string bodyRel = splitString(bodyLiteral, ',')[0];
139 
140  // check whether the current atom is a constraint
141  assert(bodyRel.size() > 0 && "body of a relation should have positive length");
142  bool isConstraint = contains(constraintList, bodyRel);
143 
144  // handle negated atom names
145  auto bodyRelAtomName = bodyRel;
146  if (bodyRel[0] == '!' && bodyRel != "!=") {
147  bodyRelAtomName = bodyRel.substr(1);
148  }
149 
150  // traverse subroutine return
151  size_t arity;
152  size_t auxiliaryArity;
153  if (isConstraint) {
154  // we only handle binary constraints, and assume arity is 4 to account for hidden provenance
155  // annotations
156  arity = 4;
157  auxiliaryArity = 2;
158  } else {
159  arity = prog.getRelation(bodyRelAtomName)->getArity();
160  auxiliaryArity = prog.getRelation(bodyRelAtomName)->getAuxiliaryArity();
161  }
162  auto tupleEnd = tupleCurInd + arity;
163 
164  // store current tuple
165  std::vector<RamDomain> subproofTuple;
166 
167  for (; tupleCurInd < tupleEnd - auxiliaryArity; tupleCurInd++) {
168  subproofTuple.push_back(ret[tupleCurInd]);
169  }
170 
171  int subproofRuleNum = ret[tupleCurInd];
172  int subproofLevelNum = ret[tupleCurInd + 1];
173 
174  tupleCurInd += 2;
175 
176  // for a negation, display the corresponding tuple and do not recurse
177  if (bodyRel[0] == '!' && bodyRel != "!=") {
178  std::stringstream joinedTuple;
179  joinedTuple << join(decodeArguments(bodyRelAtomName, subproofTuple), ", ");
180  auto joinedTupleStr = joinedTuple.str();
181  internalNode->add_child(mk<LeafNode>(bodyRel + "(" + joinedTupleStr + ")"));
182  internalNode->setSize(internalNode->getSize() + 1);
183  // for a binary constraint, display the corresponding values and do not recurse
184  } else if (isConstraint) {
185  std::stringstream joinedConstraint;
186 
187  // FIXME: We need type info in order to figure out how to print arguments.
188  BinaryConstraintOp rawBinOp = toBinaryConstraintOp(bodyRel);
189  if (isOrderedBinaryConstraintOp(rawBinOp)) {
190  joinedConstraint << subproofTuple[0] << " " << bodyRel << " " << subproofTuple[1];
191  } else {
192  joinedConstraint << bodyRel << "(\"" << symTable.resolve(subproofTuple[0]) << "\", \""
193  << symTable.resolve(subproofTuple[1]) << "\")";
194  }
195 
196  internalNode->add_child(mk<LeafNode>(joinedConstraint.str()));
197  internalNode->setSize(internalNode->getSize() + 1);
198  // otherwise, for a normal tuple, recurse
199  } else {
200  auto child =
201  explain(bodyRel, subproofTuple, subproofRuleNum, subproofLevelNum, depthLimit - 1);
202  internalNode->setSize(internalNode->getSize() + child->getSize());
203  internalNode->add_child(std::move(child));
204  }
205 
206  tupleCurInd = tupleEnd;
207  }
208 
209  return internalNode;
210  }
211 
212  Own<TreeNode> explain(std::string relName, std::vector<std::string> args, size_t depthLimit) override {
213  auto tuple = argsToNums(relName, args);
214  if (tuple.empty()) {
215  return mk<LeafNode>("Relation not found");
216  }

◆ explain() [2/2]

Own<TreeNode> souffle::ExplainProvenanceImpl::explain ( std::string  relName,
std::vector< std::string >  args,
size_t  depthLimit 
)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 218 of file ExplainProvenanceImpl.h.

223  {
224  return mk<LeafNode>("Tuple not found");
225  }
226 
227  return explain(relName, tuple, ruleNum, levelNum, depthLimit);
228  }
229 
230  Own<TreeNode> explainSubproof(std::string relName, RamDomain subproofNum, size_t depthLimit) override {
231  if (subproofNum >= (int)subproofs.size()) {
232  return mk<LeafNode>("Subproof not found");
233  }
234 

◆ explainNegation()

Own<TreeNode> souffle::ExplainProvenanceImpl::explainNegation ( std::string  relName,
size_t  ruleNum,
const std::vector< std::string > &  tuple,
std::map< std::string, std::string > &  bodyVariables 
)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 321 of file ExplainProvenanceImpl.h.

331  {
332  return !(isNumber(arg.c_str()) || arg[0] == '\"' || arg == "_");
333  };
334 
335  // get body variables
336  for (auto it = atoms.begin() + 1; it < atoms.end(); it++) {
337  auto atomRepresentation = splitString(*it, ',');
338 
339  // atomRepresentation.begin() + 1 because the first element is the relation name of the atom
340  // which is not relevant for finding variables
341  for (auto atomIt = atomRepresentation.begin() + 1; atomIt < atomRepresentation.end(); atomIt++) {
342  if (!contains(uniqueVariables, *atomIt) && !contains(headVariables, *atomIt)) {
343  // ignore non-variables
344  if (!isVariable(*atomIt)) {
345  continue;
346  }
347 
348  uniqueVariables.push_back(*atomIt);
349 
350  if (!contains(constraintList, atomRepresentation[0])) {
351  // store type of variable
352  auto currentRel = prog.getRelation(atomRepresentation[0]);
353  assert(currentRel != nullptr &&
354  ("relation " + atomRepresentation[0] + " doesn't exist").c_str());
355  variableTypes[*atomIt] =
356  *currentRel->getAttrType(atomIt - atomRepresentation.begin() - 1);
357  } else if (atomIt->find("agg_") != std::string::npos) {
358  variableTypes[*atomIt] = 'i';
359  }
360  }
361  }
362  }
363 
364  std::vector<RamDomain> args;
365 
366  size_t varCounter = 0;
367 
368  // construct arguments to pass in to the subroutine
369  // - this contains the variable bindings selected by the user
370 
371  // add number representation of tuple
372  auto tupleNums = argsToNums(relName, tuple);
373  args.insert(args.end(), tupleNums.begin(), tupleNums.end());
374  varCounter += tuple.size();
375 
376  while (varCounter < uniqueVariables.size()) {
377  auto var = uniqueVariables[varCounter];
378  auto varValue = bodyVariables[var];
379  if (variableTypes[var] == 's') {
380  if (varValue.size() >= 2 && varValue[0] == '"' && varValue[varValue.size() - 1] == '"') {
381  auto originalStr = varValue.substr(1, varValue.size() - 2);
382  args.push_back(symTable.lookup(originalStr));
383  } else {
384  // assume no quotation marks
385  args.push_back(symTable.lookup(varValue));
386  }
387  } else {
388  args.push_back(std::stoi(varValue));
389  }
390 
391  varCounter++;
392  }
393 
394  // set up return and error vectors for subroutine calling
395  std::vector<RamDomain> ret;
396 
397  // execute subroutine to get subproofs
398  prog.executeSubroutine(relName + "_" + std::to_string(ruleNum) + "_negation_subproof", args, ret);
399 
400  // ensure the subroutine returns the correct number of results
401  assert(ret.size() == atoms.size() - 1);
402 
403  // construct tree nodes
404  std::stringstream joinedArgsStr;
405  joinedArgsStr << join(tuple, ",");
406  auto internalNode = mk<InnerNode>(
407  relName + "(" + joinedArgsStr.str() + ")", "(R" + std::to_string(ruleNum) + ")");
408 
409  // store the head tuple in bodyVariables so we can print
410  for (size_t i = 0; i < headVariables.size(); i++) {
411  bodyVariables[headVariables[i]] = tuple[i];
412  }
413 
414  // traverse return vector and construct child nodes
415  // making sure we display existent and non-existent tuples correctly
416  int literalCounter = 1;
417  for (RamDomain returnCounter : ret) {
418  // check what the next contained atom is
419  bool atomExists = true;
420  if (returnCounter == 0) {
421  atomExists = false;
422  }
423 
424  // get the relation of the current atom
425  auto atomRepresentation = splitString(atoms[literalCounter], ',');
426  std::string bodyRel = atomRepresentation[0];
427 
428  // check whether the current atom is a constraint
429  bool isConstraint = contains(constraintList, bodyRel);
430 
431  // handle negated atom names
432  auto bodyRelAtomName = bodyRel;
433  if (bodyRel[0] == '!' && bodyRel != "!=") {
434  bodyRelAtomName = bodyRel.substr(1);
435  }
436 
437  // construct a label for a node containing a literal (either constraint or atom)
438  std::stringstream childLabel;
439  if (isConstraint) {
440  // for a binary constraint, display the corresponding values and do not recurse
441  assert(atomRepresentation.size() == 3 && "not a binary constraint");
442 
443  childLabel << bodyVariables[atomRepresentation[1]] << " " << bodyRel << " "
444  << bodyVariables[atomRepresentation[2]];
445  } else {
446  childLabel << bodyRel << "(";
447  for (size_t i = 1; i < atomRepresentation.size(); i++) {
448  // if it's a non-variable, print either _ for unnamed, or constant value
449  if (!isVariable(atomRepresentation[i])) {
450  childLabel << atomRepresentation[i];
451  } else {
452  childLabel << bodyVariables[atomRepresentation[i]];
453  }
454  if (i < atomRepresentation.size() - 1) {
455  childLabel << ", ";
456  }
457  }
458  childLabel << ")";
459  }
460 
461  // build a marker for existence of body atoms
462  if (atomExists) {
463  childLabel << " ✓";
464  } else {
465  childLabel << " x";
466  }
467 
468  internalNode->add_child(mk<LeafNode>(childLabel.str()));
469  internalNode->setSize(internalNode->getSize() + 1);
470 
471  literalCounter++;
472  }
473 
474  return internalNode;
475  }
476 
477  std::string getRule(std::string relName, size_t ruleNum) override {
478  auto key = make_pair(relName, ruleNum);
479 
480  auto rule = rules.find(key);
481  if (rule == rules.end()) {

◆ explainNegationGetVariables()

std::vector<std::string> souffle::ExplainProvenanceImpl::explainNegationGetVariables ( std::string  relName,
std::vector< std::string >  args,
size_t  ruleNum 
)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 256 of file ExplainProvenanceImpl.h.

256  {
257  // return a sentinel value
258  return std::vector<std::string>({"@"});
259  }
260 
261  // atom meta information stored for the current rule
262  auto atoms = info[std::make_pair(relName, ruleNum)];
263 
264  // the info stores the set of atoms, if there is only 1 atom, then it must be the head, so it must be
265  // a fact
266  if (atoms.size() <= 1) {
267  return std::vector<std::string>({"@fact"});
268  }
269 
270  // atoms[0] represents variables in the head atom
271  auto headVariables = splitString(atoms[0], ',');
272 
273  auto isVariable = [&](std::string arg) {
274  return !(isNumber(arg.c_str()) || arg[0] == '\"' || arg == "_");
275  };
276 
277  // check that head variable bindings make sense, i.e. for a head like a(x, x), make sure both x are
278  // the same value
279  std::map<std::string, std::string> headVariableMapping;
280  for (size_t i = 0; i < headVariables.size(); i++) {
281  if (!isVariable(headVariables[i])) {
282  continue;
283  }
284 
285  if (headVariableMapping.find(headVariables[i]) == headVariableMapping.end()) {
286  headVariableMapping[headVariables[i]] = args[i];
287  } else {
288  if (headVariableMapping[headVariables[i]] != args[i]) {
289  return std::vector<std::string>({"@non_matching"});
290  }
291  }
292  }
293 
294  // get body variables
295  std::vector<std::string> uniqueBodyVariables;
296  for (auto it = atoms.begin() + 1; it < atoms.end(); it++) {
297  auto atomRepresentation = splitString(*it, ',');
298 
299  // atomRepresentation.begin() + 1 because the first element is the relation name of the atom
300  // which is not relevant for finding variables
301  for (auto atomIt = atomRepresentation.begin() + 1; atomIt < atomRepresentation.end(); atomIt++) {
302  if (!isVariable(*atomIt)) {
303  continue;
304  }
305 
306  if (!contains(uniqueBodyVariables, *atomIt) && !contains(headVariables, *atomIt)) {
307  uniqueBodyVariables.push_back(*atomIt);
308  }
309  }
310  }
311 
312  return uniqueBodyVariables;
313  }
314 
315  Own<TreeNode> explainNegation(std::string relName, size_t ruleNum, const std::vector<std::string>& tuple,
316  std::map<std::string, std::string>& bodyVariables) override {
317  // construct a vector of unique variables that occur in the rule
318  std::vector<std::string> uniqueVariables;
319 

◆ explainSubproof()

Own<TreeNode> souffle::ExplainProvenanceImpl::explainSubproof ( std::string  relName,
RamDomain  subproofNum,
size_t  depthLimit 
)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 236 of file ExplainProvenanceImpl.h.

251  {
252  std::vector<std::string> variables;
253 
254  // check that the tuple actually doesn't exist

◆ findQuerySolution()

void souffle::ExplainProvenanceImpl::findQuerySolution ( const std::vector< Relation * > &  varRels,
const std::map< std::string, Equivalence > &  nameToEquivalence,
const ConstConstraint constConstraints 
)
inlineprivate

Definition at line 800 of file ExplainProvenanceImpl.h.

807  {
808  bool isSolution = true;
809 
810  // vector contains the tuples the iterators currently points to
811  std::vector<tuple> element;
812  for (auto it : varRelationIterators) {
813  element.push_back(*it);
814  }
815  // check if tuple satisfies variable equivalence
816  for (auto var : nameToEquivalence) {
817  if (!var.second.verify(element)) {
818  isSolution = false;
819  break;
820  }
821  }
822  if (isSolution) {
823  // check if tuple satisfies constant constraints
824  isSolution = constConstraints.verify(element);
825  }
826 
827  if (isSolution) {
828  std::cout << solution.str(); // print previous solution (if any)
829  solution.str(std::string()); // reset solution and process
830 
831  size_t c = 0;
832  for (auto&& var : nameToEquivalence) {
833  auto idx = var.second.getFirstIdx();
834  auto raw = element[idx.first][idx.second];
835 
836  solution << var.second.getSymbol() << " = ";
837  switch (var.second.getType()) {
838  case 'i': solution << ramBitCast<RamSigned>(raw); break;
839  case 'f': solution << ramBitCast<RamFloat>(raw); break;
840  case 'u': solution << ramBitCast<RamUnsigned>(raw); break;
841  case 's': solution << prog.getSymbolTable().resolve(raw); break;
842  default: fatal("invalid type: `%c`", var.second.getType());
843  }
844 
845  auto sep = ++c < nameToEquivalence.size() ? ", " : " ";
846  solution << sep;
847  }
848 
849  solutionCount++;
850  // query has more than one solution; query whether to find next solution or stop
851  if (1 < solutionCount) {
852  for (std::string input; getline(std::cin, input);) {
853  if (input == ";") break; // print next solution?
854  if (input == ".") return; // break from query?
855 
856  std::cout << "use ; to find next solution, use . to break from current query\n";
857  }
858  }
859  }
860 
861  // increment the iterators
862  size_t i = varRels.size() - 1;
863  bool terminate = true;
864  for (auto it = varRelationIterators.rbegin(); it != varRelationIterators.rend(); ++it) {
865  if ((++(*it)) != varRels[i]->end()) {
866  terminate = false;
867  break;
868  } else {
869  (*it) = varRels[i]->begin();
870  --i;
871  }
872  }
873 
874  if (terminate) {
875  // if there is no solution, output false
876  if (solutionCount == 0) {
877  std::cout << "false." << std::endl;
878  // otherwise print the last solution
879  } else {
880  std::cout << solution.str() << "." << std::endl;
881  }
882  break;
883  }
884  }
885  }
886 
887  // check if constTuple exists in relation
888  bool containsTuple(Relation* relation, const std::vector<RamDomain>& constTuple) {
889  bool tupleExist = false;
890  for (auto it = relation->begin(); it != relation->end(); ++it) {
891  bool eq = true;

◆ findTuple()

std::tuple<int, int> souffle::ExplainProvenanceImpl::findTuple ( const std::string &  relName,
std::vector< RamDomain tup 
)
inlineprivate

Definition at line 740 of file ExplainProvenanceImpl.h.

742  : *rel) {
743  bool match = true;
744  std::vector<RamDomain> currentTuple;
745 
746  for (arity_type i = 0; i < rel->getPrimaryArity(); i++) {
747  RamDomain n;
748  if (*rel->getAttrType(i) == 's') {
749  std::string s;
750  tuple >> s;
752  } else if (*rel->getAttrType(i) == 'f') {
753  RamFloat element;
754  tuple >> element;
755  n = ramBitCast(element);
756  } else if (*rel->getAttrType(i) == 'u') {
757  RamUnsigned element;
758  tuple >> element;
759  n = ramBitCast(element);
760  } else {
761  tuple >> n;
762  }
763 
764  currentTuple.push_back(n);
765 
766  if (n != tup[i]) {
767  match = false;
768  break;
769  }
770  }
771 
772  if (match) {
773  RamDomain ruleNum;
774  tuple >> ruleNum;
775 
776  RamDomain levelNum;
777  tuple >> levelNum;
778 
779  return std::make_tuple(ruleNum, levelNum);
780  }
781  }
782 
783  // if no tuple exists
784  return std::make_tuple(-1, -1);
785  }
786 
787  /*
788  * Find solution for parameterised query satisfying constant constraints and equivalence constraints
789  * @param varRels, reference to vector of relation of tuple contains at least one variable in its
790  * arguments
791  * @param nameToEquivalence, reference to variable name and corresponding equivalence class

References i, n, souffle::ramBitCast(), and rel().

Here is the call graph for this function:

◆ getRule()

std::string souffle::ExplainProvenanceImpl::getRule ( std::string  relName,
size_t  ruleNum 
)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 483 of file ExplainProvenanceImpl.h.

483  {
484  return rule->second;
485  }
486  }
487 
488  std::vector<std::string> getRules(const std::string& relName) override {
489  std::vector<std::string> relRules;
490  // go through all rules
491  for (auto& rule : rules) {
492  if (rule.first.first == relName) {

◆ getRules()

std::vector<std::string> souffle::ExplainProvenanceImpl::getRules ( const std::string &  relName)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 494 of file ExplainProvenanceImpl.h.

500  {
501  auto rel = prog.getRelation(relName);
502 
503  if (rel == nullptr) {
504  return "No relation found\n";

◆ measureRelation()

std::string souffle::ExplainProvenanceImpl::measureRelation ( std::string  relName)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 506 of file ExplainProvenanceImpl.h.

510  {
511  skip = 1;
512  }
513 
514  std::stringstream ss;
515 
516  auto before_time = std::chrono::high_resolution_clock::now();
517 
518  int numTuples = 0;
519  int proc = 0;
520  for (auto& tuple : *rel) {
521  auto tupleStart = std::chrono::high_resolution_clock::now();
522 
523  if (numTuples % skip != 0) {
524  numTuples++;
525  continue;
526  }
527 
528  std::vector<RamDomain> currentTuple;
529  for (arity_type i = 0; i < rel->getPrimaryArity(); i++) {
530  RamDomain n;
531  if (*rel->getAttrType(i) == 's') {
532  std::string s;
533  tuple >> s;
535  } else if (*rel->getAttrType(i) == 'f') {
536  RamFloat element;
537  tuple >> element;
538  n = ramBitCast(element);
539  } else if (*rel->getAttrType(i) == 'u') {
540  RamUnsigned element;
541  tuple >> element;
542  n = ramBitCast(element);
543  } else {
544  tuple >> n;
545  }
546 
547  currentTuple.push_back(n);
548  }
549 
550  RamDomain ruleNum;
551  tuple >> ruleNum;
552 
553  RamDomain levelNum;
554  tuple >> levelNum;
555 
556  std::cout << "Tuples expanded: "
557  << explain(relName, currentTuple, ruleNum, levelNum, 10000)->getSize();
558 
559  numTuples++;
560  proc++;
561 
562  auto tupleEnd = std::chrono::high_resolution_clock::now();
563  auto tupleDuration =
564  std::chrono::duration_cast<std::chrono::duration<double>>(tupleEnd - tupleStart);
565 
566  std::cout << ", Time: " << tupleDuration.count() << "\n";
567  }
568 
569  auto after_time = std::chrono::high_resolution_clock::now();
570  auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(after_time - before_time);
571 
572  ss << "total: " << proc << " ";
573  ss << duration.count() << std::endl;
574 
575  return ss.str();
576  }
577 
578  void printRulesJSON(std::ostream& os) override {
579  os << "\"rules\": [\n";
580  bool first = true;
581  for (auto const& cur : rules) {
582  if (first) {

◆ printRulesJSON()

void souffle::ExplainProvenanceImpl::printRulesJSON ( std::ostream &  os)
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 584 of file ExplainProvenanceImpl.h.

584  {
585  os << ",\n";
586  }
587  os << "\t{ \"rule-number\": \"(R" << cur.first.second << ")\", \"rule\": \""
588  << stringify(cur.second) << "\"}";
589  }
590  os << "\n]\n";
591  }
592 
593  void queryProcess(const std::vector<std::pair<std::string, std::vector<std::string>>>& rels) override {
594  std::regex varRegex("[a-zA-Z_][a-zA-Z_0-9]*", std::regex_constants::extended);
595  std::regex symbolRegex("\"([^\"]*)\"", std::regex_constants::extended);
596  std::regex numberRegex("[0-9]+", std::regex_constants::extended);
597 

◆ queryProcess()

void souffle::ExplainProvenanceImpl::queryProcess ( const std::vector< std::pair< std::string, std::vector< std::string >>> &  rels)
inlineoverridevirtual

Process query with given arguments.

Parameters
rels,vectorof relation, argument pairs

Implements souffle::ExplainProvenance.

Definition at line 599 of file ExplainProvenanceImpl.h.

613  : rels) {
614  Relation* relation = prog.getRelation(rel.first);
615  // number/symbol index for constant arguments in tuple
616  std::vector<RamDomain> constTuple;
617  // relation does not exist
618  if (relation == nullptr) {
619  std::cout << "Relation <" << rel.first << "> does not exist" << std::endl;
620  return;
621  }
622  // arity error
623  if (relation->getPrimaryArity() != rel.second.size()) {
624  std::cout << "<" + rel.first << "> has arity of " << relation->getPrimaryArity() << std::endl;
625  return;
626  }
627 
628  // check if args contain variable
629  bool containVar = false;
630  for (size_t j = 0; j < rel.second.size(); ++j) {
631  // arg is a variable
632  if (std::regex_match(rel.second[j], argsMatcher, varRegex)) {
633  containVar = true;
634  auto nameToEquivalenceIter = nameToEquivalence.find(argsMatcher[0]);
635  // if variable has not shown up before, create an equivalence class for add it to
636  // nameToEquivalence map, otherwise add its indices to corresponding equivalence class
637  if (nameToEquivalenceIter == nameToEquivalence.end()) {
638  nameToEquivalence.insert(
639  {argsMatcher[0], Equivalence(*(relation->getAttrType(j)), argsMatcher[0],
640  std::make_pair(idx, j))});
641  } else {
642  nameToEquivalenceIter->second.push_back(std::make_pair(idx, j));
643  }
644  continue;
645  }
646 
647  RamDomain rd;
648  switch (*(relation->getAttrType(j))) {
649  case 's':
650  if (!std::regex_match(rel.second[j], argsMatcher, symbolRegex)) {
651  std::cout << argsMatcher.str(0) << " does not match type defined in relation"
652  << std::endl;
653  return;
654  }
655  rd = prog.getSymbolTable().lookup(argsMatcher[1]);
656  break;
657  case 'f':
658  if (!canBeParsedAsRamFloat(rel.second[j])) {
659  std::cout << rel.second[j] << " does not match type defined in relation"
660  << std::endl;
661  return;
662  }
663  rd = ramBitCast(RamFloatFromString(rel.second[j]));
664  break;
665  case 'i':
666  if (!canBeParsedAsRamSigned(rel.second[j])) {
667  std::cout << rel.second[j] << " does not match type defined in relation"
668  << std::endl;
669  return;
670  }
671  rd = ramBitCast(RamSignedFromString(rel.second[j]));
672  break;
673  case 'u':
674  if (!canBeParsedAsRamUnsigned(rel.second[j])) {
675  std::cout << rel.second[j] << " does not match type defined in relation"
676  << std::endl;
677  return;
678  }
679  rd = ramBitCast(RamUnsignedFromString(rel.second[j]));
680  break;
681  default: continue;
682  }
683 
684  constConstraints.push_back(std::make_pair(std::make_pair(idx, j), rd));
685  if (!containVar) {
686  constTuple.push_back(rd);
687  }
688  }
689 
690  // if tuple does not contain any variable, check if existence of the tuple
691  if (!containVar) {
692  bool tupleExist = containsTuple(relation, constTuple);
693 
694  // if relation contains this tuple, remove all related constraints
695  if (tupleExist) {
696  constConstraints.getConstraints().erase(constConstraints.getConstraints().end() -
697  relation->getArity() +
698  relation->getAuxiliaryArity(),
699  constConstraints.getConstraints().end());
700  // otherwise, there is no solution for given query
701  } else {
702  std::cout << "false." << std::endl;
703  std::cout << "Tuple " << rel.first << "(";
704  for (size_t l = 0; l < rel.second.size() - 1; ++l) {
705  std::cout << rel.second[l] << ", ";
706  }
707  std::cout << rel.second.back() << ") does not exist" << std::endl;
708  return;
709  }
710  } else {
711  varRels.push_back(relation);
712  ++idx;
713  }
714  }
715 
716  // if varRels size is 0, all given tuples only contain constant args and exist, no variable to
717  // resolve, Output true and return
718  if (varRels.size() == 0) {
719  std::cout << "true." << std::endl;
720  return;
721  }
722 
723  // find solution for parameterised query
724  findQuerySolution(varRels, nameToEquivalence, constConstraints);
725  }
726 
727 private:
728  std::map<std::pair<std::string, size_t>, std::vector<std::string>> info;
729  std::map<std::pair<std::string, size_t>, std::string> rules;
730  std::vector<std::vector<RamDomain>> subproofs;
731  std::vector<std::string> constraintList = {

References souffle::canBeParsedAsRamFloat(), souffle::canBeParsedAsRamSigned(), souffle::canBeParsedAsRamUnsigned(), souffle::ConstConstraint::getConstraints(), j, l, souffle::ConstConstraint::push_back(), souffle::ramBitCast(), souffle::RamFloatFromString(), souffle::RamSignedFromString(), souffle::RamUnsignedFromString(), rel(), and relation.

Here is the call graph for this function:

◆ setup()

void souffle::ExplainProvenanceImpl::setup ( )
inlineoverridevirtual

Implements souffle::ExplainProvenance.

Definition at line 62 of file ExplainProvenanceImpl.h.

62  {
63  continue;
64  }
65 
66  // find all the info tuples
67  for (auto& tuple : *rel) {
68  std::vector<std::string> bodyLiterals;
69 
70  RamDomain ruleNum;
71  tuple >> ruleNum;
72 
73  for (size_t i = 1; i + 1 < rel->getArity(); i++) {
74  std::string bodyLit;
75  tuple >> bodyLit;
76  bodyLiterals.push_back(bodyLit);
77  }
78 
79  std::string rule;
80  tuple >> rule;
81 
82  info.insert({std::make_pair(name.substr(0, name.find(".@info")), ruleNum), bodyLiterals});
83  rules.insert({std::make_pair(name.substr(0, name.find(".@info")), ruleNum), rule});
84  }
85  }
86  }
87 
88  Own<TreeNode> explain(
89  std::string relName, std::vector<RamDomain> tuple, int ruleNum, int levelNum, size_t depthLimit) {
90  std::stringstream joinedArgs;
91  joinedArgs << join(decodeArguments(relName, tuple), ", ");
92  auto joinedArgsStr = joinedArgs.str();

Field Documentation

◆ constraintList

std::vector<std::string> souffle::ExplainProvenanceImpl::constraintList
private
Initial value:
= {
"=", "!=", "<", "<=", ">=", ">", "match", "contains", "not_match", "not_contains"}

Definition at line 737 of file ExplainProvenanceImpl.h.

◆ info

std::map<std::pair<std::string, size_t>, std::vector<std::string> > souffle::ExplainProvenanceImpl::info
private

Definition at line 734 of file ExplainProvenanceImpl.h.

◆ rules

std::map<std::pair<std::string, size_t>, std::string> souffle::ExplainProvenanceImpl::rules
private

Definition at line 735 of file ExplainProvenanceImpl.h.

◆ subproofs

std::vector<std::vector<RamDomain> > souffle::ExplainProvenanceImpl::subproofs
private

Definition at line 736 of file ExplainProvenanceImpl.h.


The documentation for this class was generated from the following file:
souffle::ExplainProvenanceImpl::findQuerySolution
void findQuerySolution(const std::vector< Relation * > &varRels, const std::map< std::string, Equivalence > &nameToEquivalence, const ConstConstraint &constConstraints)
Definition: ExplainProvenanceImpl.h:800
souffle::RamUnsigned
uint32_t RamUnsigned
Definition: RamTypes.h:58
souffle::RamSignedFromString
RamSigned RamSignedFromString(const std::string &str, std::size_t *position=nullptr, const int base=10)
Converts a string to a RamSigned.
Definition: StringUtil.h:51
souffle::SymbolTable::resolve
const std::string & resolve(const RamDomain index) const
Find a symbol in the table by its index, note that this gives an error if the index is out of bounds.
Definition: SymbolTable.h:154
souffle::ExplainProvenanceImpl::info
std::map< std::pair< std::string, size_t >, std::vector< std::string > > info
Definition: ExplainProvenanceImpl.h:734
souffle::RamDomain
int32_t RamDomain
Definition: RamTypes.h:56
souffle::isNumber
bool isNumber(const char *str)
Check whether a string is a sequence of digits.
Definition: StringUtil.h:217
souffle::canBeParsedAsRamFloat
bool canBeParsedAsRamFloat(const std::string &string)
Can a string be parsed as RamFloat.
Definition: StringUtil.h:192
souffle::ExplainProvenanceImpl::getRules
std::vector< std::string > getRules(const std::string &relName) override
Definition: ExplainProvenanceImpl.h:494
souffle::ExplainProvenanceImpl::subproofs
std::vector< std::vector< RamDomain > > subproofs
Definition: ExplainProvenanceImpl.h:736
souffle::contains
bool contains(const C &container, const typename C::value_type &element)
A utility to check generically whether a given element is contained in a given container.
Definition: ContainerUtil.h:75
souffle::ExplainProvenance::prog
SouffleProgram & prog
Definition: ExplainProvenance.h:197
relation
Relation & relation
Definition: Reader.h:130
souffle::RamFloat
float RamFloat
Definition: RamTypes.h:60
souffle::ExplainProvenanceImpl::explainSubproof
Own< TreeNode > explainSubproof(std::string relName, RamDomain subproofNum, size_t depthLimit) override
Definition: ExplainProvenanceImpl.h:236
souffle::ExplainProvenanceImpl::explainNegation
Own< TreeNode > explainNegation(std::string relName, size_t ruleNum, const std::vector< std::string > &tuple, std::map< std::string, std::string > &bodyVariables) override
Definition: ExplainProvenanceImpl.h:321
souffle::ExplainProvenanceImpl::constraintList
std::vector< std::string > constraintList
Definition: ExplainProvenanceImpl.h:737
n
var n
Definition: htmlJsChartistMin.h:15
j
var j
Definition: htmlJsChartistMin.h:15
souffle::SymbolTable::lookup
RamDomain lookup(const std::string &symbol)
Find the index of a symbol in the table, inserting a new symbol if it does not exist there already.
Definition: SymbolTable.h:124
souffle::now
time_point now()
Definition: MiscUtil.h:89
souffle::SymbolTable::lookupExisting
RamDomain lookupExisting(const std::string &symbol) const
Finds the index of a symbol in the table, giving an error if it's not found.
Definition: SymbolTable.h:133
l
var l
Definition: htmlJsChartistMin.h:15
souffle::ExplainProvenanceImpl::queryProcess
void queryProcess(const std::vector< std::pair< std::string, std::vector< std::string >>> &rels) override
Process query with given arguments.
Definition: ExplainProvenanceImpl.h:599
souffle::stringify
std::string stringify(const std::string &input)
Stringify a string using escapes for escape, newline, tab, double-quotes and semicolons.
Definition: StringUtil.h:334
i
size_t i
Definition: json11.h:663
souffle::ExplainProvenanceImpl::getRule
std::string getRule(std::string relName, size_t ruleNum) override
Definition: ExplainProvenanceImpl.h:483
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::ExplainProvenanceImpl::printRulesJSON
void printRulesJSON(std::ostream &os) override
Definition: ExplainProvenanceImpl.h:584
souffle::ExplainProvenance::symTable
SymbolTable & symTable
Definition: ExplainProvenance.h:198
souffle::ExplainProvenance::argsToNums
std::vector< RamDomain > argsToNums(const std::string &relName, const std::vector< std::string > &args) const
Definition: ExplainProvenance.h:200
souffle::toBinaryConstraintOp
BinaryConstraintOp toBinaryConstraintOp(const std::string &symbol)
Converts symbolic representation of an operator to the operator.
Definition: BinaryConstraintOps.h:371
souffle::canBeParsedAsRamUnsigned
bool canBeParsedAsRamUnsigned(const std::string &string)
Can a string be parsed as RamUnsigned.
Definition: StringUtil.h:179
souffle::BinaryConstraintOp
BinaryConstraintOp
Binary Constraint Operators.
Definition: BinaryConstraintOps.h:41
souffle::SouffleProgram::getAllRelations
std::vector< Relation * > getAllRelations() const
Getter of allRelations, which this vector structure contains all relations.
Definition: SouffleInterface.h:893
souffle::test::duration
long duration(const time_point &start, const time_point &end)
Definition: btree_multiset_test.cpp:406
souffle::ExplainProvenance::decodeArguments
std::vector< std::string > decodeArguments(const std::string &relName, const std::vector< RamDomain > &nums) const
Decode arguments from their ram representation and return as strings.
Definition: ExplainProvenance.h:219
souffle::Relation::getAuxiliaryArity
virtual arity_type getAuxiliaryArity() const =0
Return the number of auxiliary attributes.
souffle::ExplainProvenanceImpl::explain
Own< TreeNode > explain(std::string relName, std::vector< RamDomain > tuple, int ruleNum, int levelNum, size_t depthLimit)
Definition: ExplainProvenanceImpl.h:94
souffle::SouffleProgram::executeSubroutine
virtual void executeSubroutine(std::string, const std::vector< RamDomain > &, std::vector< RamDomain > &)
Execute a subroutine.
Definition: SouffleInterface.h:903
souffle::SouffleProgram::getRelation
Relation * getRelation(const std::string &name) const
Get Relation by its name from relationMap, if relation not found, return a nullptr.
Definition: SouffleInterface.h:827
souffle::Relation::getArity
virtual arity_type getArity() const =0
Return the arity of a relation.
souffle::canBeParsedAsRamSigned
bool canBeParsedAsRamSigned(const std::string &string)
Can a string be parsed as RamSigned.
Definition: StringUtil.h:162
souffle::splitString
std::vector< std::string > splitString(const std::string &str, char delimiter)
Splits a string given a delimiter.
Definition: StringUtil.h:321
rule
Rule & rule
Definition: Reader.h:85
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
souffle::ExplainProvenanceImpl::arity_type
Relation::arity_type arity_type
Definition: ExplainProvenanceImpl.h:55
souffle::RamUnsignedFromString
RamUnsigned RamUnsignedFromString(const std::string &str, std::size_t *position=nullptr, const int base=10)
Converts a string to a RamUnsigned.
Definition: StringUtil.h:110
souffle::ramBitCast
To ramBitCast(From source)
In C++20 there will be a new way to cast between types by reinterpreting bits (std::bit_cast),...
Definition: RamTypes.h:87
souffle::ExplainProvenanceImpl::rules
std::map< std::pair< std::string, size_t >, std::string > rules
Definition: ExplainProvenanceImpl.h:735
souffle::ExplainProvenanceImpl::containsTuple
bool containsTuple(Relation *relation, const std::vector< RamDomain > &constTuple)
Definition: ExplainProvenanceImpl.h:894
souffle::RamFloatFromString
RamFloat RamFloatFromString(const std::string &str, std::size_t *position=nullptr)
Converts a string to a RamFloat.
Definition: StringUtil.h:93
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::isOrderedBinaryConstraintOp
bool isOrderedBinaryConstraintOp(const BinaryConstraintOp op)
Determines whether arguments of constraint are orderable.
Definition: BinaryConstraintOps.h:389
souffle::SouffleProgram::getSymbolTable
virtual SymbolTable & getSymbolTable()=0
Get the symbol table of the program.
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336