souffle  2.0.2-371-g6315b36
Public Member Functions | Data Fields | Private Member Functions
souffle::Explain Class Referenceabstract

#include <Explain.h>

Collaboration diagram for souffle::Explain:
Collaboration graph

Public Member Functions

virtual void explain ()=0
 
 Explain (ExplainProvenance &prov)
 
bool processCommand (std::string &commandLine)
 
 ~Explain ()=default
 

Data Fields

ExplainProvenanceprov
 

Private Member Functions

virtual std::string getInput ()=0
 
std::pair< std::string, std::vector< std::string > > parseTuple (const std::string &str)
 Parse tuple, split into relation name and values. More...
 
virtual void printError (const std::string &error)=0
 
virtual void printInfo (const std::string &info)=0
 
virtual void printPrompt (const std::string &prompt)=0
 
virtual void printTree (Own< TreeNode > tree)=0
 

Detailed Description

Definition at line 68 of file Explain.h.

Constructor & Destructor Documentation

◆ Explain()

souffle::Explain::Explain ( ExplainProvenance prov)
inline

Definition at line 72 of file Explain.h.

72 : prov(prov) {}

◆ ~Explain()

souffle::Explain::~Explain ( )
default

Member Function Documentation

◆ explain()

virtual void souffle::Explain::explain ( )
pure virtual

◆ getInput()

virtual std::string souffle::Explain::getInput ( )
privatepure virtual

Referenced by processCommand().

◆ parseTuple()

std::pair<std::string, std::vector<std::string> > souffle::Explain::parseTuple ( const std::string &  str)
inlineprivate

Parse tuple, split into relation name and values.

Parameters
strThe string to parse, should be something like "R(x1, x2, x3, ...)"

Definition at line 298 of file Explain.h.

References str.

Referenced by processCommand().

◆ printError()

virtual void souffle::Explain::printError ( const std::string &  error)
privatepure virtual

Referenced by processCommand().

◆ printInfo()

virtual void souffle::Explain::printInfo ( const std::string &  info)
privatepure virtual

Referenced by processCommand().

◆ printPrompt()

virtual void souffle::Explain::printPrompt ( const std::string &  prompt)
privatepure virtual

Referenced by processCommand().

◆ printTree()

virtual void souffle::Explain::printTree ( Own< TreeNode tree)
privatepure virtual

Referenced by processCommand().

◆ processCommand()

bool souffle::Explain::processCommand ( std::string &  commandLine)
inline

Definition at line 77 of file Explain.h.

77  {
78  std::vector<std::string> command = split(commandLine, ' ', 1);
79 
80  if (command.empty()) {
81  return true;
82  }
83 
84  if (command[0] == "setdepth") {
85  if (command.size() != 2) {
86  printError("Usage: setdepth <depth>\n");
87  return true;
88  }
89  try {
90  ExplainConfig::getExplainConfig().depthLimit = std::stoi(command[1]);
91  } catch (std::exception& e) {
92  printError("<" + command[1] + "> is not a valid depth\n");
93  return true;
94  }
95  printInfo("Depth is now " + std::to_string(ExplainConfig::getExplainConfig().depthLimit) + "\n");
96  } else if (command[0] == "explain") {
97  std::pair<std::string, std::vector<std::string>> query;
98  if (command.size() != 2) {
99  printError("Usage: explain relation_name(\"<string element1>\", <number element2>, ...)\n");
100  return true;
101  }
102  query = parseTuple(command[1]);
103  printTree(prov.explain(query.first, query.second, ExplainConfig::getExplainConfig().depthLimit));
104  } else if (command[0] == "subproof") {
105  std::pair<std::string, std::vector<std::string>> query;
106  int label = -1;
107  if (command.size() <= 1) {
108  printError("Usage: subproof relation_name(<label>)\n");
109  return true;
110  }
111  query = parseTuple(command[1]);
112  label = std::stoi(query.second[0]);
114  } else if (command[0] == "explainnegation") {
115  std::pair<std::string, std::vector<std::string>> query;
116  if (command.size() != 2) {
117  printError(
118  "Usage: explainnegation relation_name(\"<string element1>\", <number element2>, "
119  "...)\n");
120  return true;
121  }
122  query = parseTuple(command[1]);
123 
124  // a counter for the rule numbers
125  size_t i = 1;
126  std::string rules;
127 
128  // if there are no rules, then this must be an EDB relation
129  if (prov.getRules(query.first).size() == 0) {
130  printInfo("The tuple would be an input fact!\n");
131  return true;
132  }
133 
134  for (auto rule : prov.getRules(query.first)) {
135  rules += std::to_string(i) + ": ";
136  rules += rule;
137  rules += "\n\n";
138  i++;
139  }
140  printInfo(rules);
141 
142  printPrompt("Pick a rule number: ");
143 
144  std::string ruleNum = getInput();
145  auto variables = prov.explainNegationGetVariables(query.first, query.second, std::stoi(ruleNum));
146 
147  // @ and @non_matching are special sentinel values returned by ExplainProvenance
148  if (variables.size() == 1 && variables[0] == "@") {
149  printInfo("The tuple exists, cannot explain negation of it!\n");
150  return true;
151  } else if (variables.size() == 1 && variables[0] == "@non_matching") {
152  printInfo("The variable bindings don't match, cannot explain!\n");
153  return true;
154  } else if (variables.size() == 1 && variables[0] == "@fact") {
155  printInfo("The rule is a fact!\n");
156  return true;
157  }
158 
159  std::map<std::string, std::string> varValues;
160  for (auto var : variables) {
161  printPrompt("Pick a value for " + var + ": ");
162  varValues[var] = getInput();
163  }
164 
165  printTree(prov.explainNegation(query.first, std::stoi(ruleNum), query.second, varValues));
166  } else if (command[0] == "rule" && command.size() == 2) {
167  auto query = split(command[1], ' ');
168  if (query.size() != 2) {
169  printError("Usage: rule <relation name> <rule number>\n");
170  return true;
171  }
172  try {
173  printInfo(prov.getRule(query[0], std::stoi(query[1])) + "\n");
174  } catch (std::exception& e) {
175  printError("Usage: rule <relation name> <rule number>\n");
176  }
177  } else if (command[0] == "measure") {
178  try {
179  printInfo(prov.measureRelation(command[1]));
180  } catch (std::exception& e) {
181  printError("Usage: measure <relation name>\n");
182  }
183  } else if (command[0] == "output") {
184  if (command.size() == 2) {
185  // assign a new filestream, the old one is deleted by unique_ptr
186  ExplainConfig::getExplainConfig().outputStream = mk<std::ofstream>(command[1]);
187  } else if (command.size() == 1) {
189  } else {
190  printError("Usage: output [<filename>]\n");
191  }
192  } else if (command[0] == "format") {
193  if (command.size() == 2 && command[1] == "json") {
195  } else if (command.size() == 2 && command[1] == "proof") {
197  } else {
198  printError("Usage: format <json|proof>\n");
199  }
200  } else if (command[0] == "exit" || command[0] == "q" || command[0] == "quit") {
201  // close file stream so that output is actually written to file
202  printPrompt("Exiting explain\n");
203  return false;
204  } else if (command[0] == "query") {
205  // if there is no given relations, return directly
206  if (command.size() != 2) {
207  printError(
208  "Usage: query <relation1>(<element1>, <element2>, ...), "
209  "<relation2>(<element1>, <element2>, ...), ...\n");
210  return true;
211  }
212  // vector relations stores relation name, args pair parsed by parseQueryTuple()
213  std::vector<std::pair<std::string, std::vector<std::string>>> relations;
214  // regex for relation string
215  std::regex relationRegex(
216  "([a-zA-Z0-9_.-]*)[[:blank:]]*\\(([[:blank:]]*([0-9]+|\"[^\"]*\"|[a-zA-Z_][a-zA-Z_0-9]*)("
217  "[[:blank:]]*,[[:blank:]]*(["
218  "0-"
219  "9]+|\"[^\"]*\"|[a-zA-Z_][a-zA-Z_0-9]*))*)?\\)",
220  std::regex_constants::extended);
221  std::smatch relationMatcher;
222  std::string relationStr = command[1];
223  // use relationRegex to match each relation string and call parseQueryTuple() to parse the
224  // relation name and arguments
225  while (std::regex_search(relationStr, relationMatcher, relationRegex)) {
226  relations.push_back(parseQueryTuple(relationMatcher[0]));
227 
228  // check return value for parseQueryTuple, return if relation name is empty string or tuple
229  // arguments is empty
230  if (relations.back().first.size() == 0 || relations.back().second.size() == 0) {
231  printError(
232  "Usage: query <relation1>(<element1>, <element2>, ...), "
233  "<relation2>(<element1>, <element2>, ...), ...\n");
234  return true;
235  }
236  relationStr = relationMatcher.suffix().str();
237  }
238 
239  // is no valid relation can be identified, return directly
240  if (relations.size() == 0) {
241  printError(
242  "Usage: query <relation1>(<element1>, <element2>, ...), "
243  "<relation2>(<element1>, <element2>, ...), ...\n");
244  return true;
245  }
246 
247  // call queryProcess function to process query
249  } else {
250  printError(
251  "\n----------\n"
252  "Commands:\n"
253  "----------\n"
254  "setdepth <depth>: Set a limit for printed derivation tree height\n"
255  "explain <relation>(<element1>, <element2>, ...): Prints derivation tree\n"
256  "explainnegation <relation>(<element1>, <element2>, ...): Enters an interactive\n"
257  " interface where the non-existence of a tuple can be explained\n"
258  "subproof <relation>(<label>): Prints derivation tree for a subproof, label is\n"
259  " generated if a derivation tree exceeds height limit\n"
260  "rule <relation name> <rule number>: Prints a rule\n"
261  "output <filename>: Write output into a file, or provide empty filename to\n"
262  " disable output\n"
263  "format <json|proof>: switch format between json and proof-trees\n"
264  "query <relation1>(<element1>, <element2>, ...), <relation2>(<element1>, <element2>), "
265  "... :\n"
266  "check existence of constant tuples or find solutions for parameterised tuples\n"
267  "for parameterised query, use semicolon to find next solution and dot to break from "
268  "query\n"
269  "exit: Exits this interface\n\n");
270  }
271 
272  return true;
273  }

References souffle::ExplainConfig::depthLimit, e, souffle::ExplainProvenance::explain(), souffle::ExplainProvenance::explainNegation(), souffle::ExplainProvenance::explainNegationGetVariables(), souffle::ExplainProvenance::explainSubproof(), souffle::ExplainConfig::getExplainConfig(), getInput(), souffle::ExplainProvenance::getRule(), souffle::ExplainProvenance::getRules(), i, souffle::ExplainConfig::json, souffle::ExplainProvenance::measureRelation(), souffle::ExplainConfig::outputStream, parseTuple(), printError(), printInfo(), printPrompt(), printTree(), prov, souffle::ExplainProvenance::queryProcess(), relations, rule, and souffle::split().

Here is the call graph for this function:

Field Documentation

◆ prov

ExplainProvenance& souffle::Explain::prov

Definition at line 70 of file Explain.h.

Referenced by processCommand().


The documentation for this class was generated from the following file:
souffle::ExplainProvenance::explainNegation
virtual Own< TreeNode > explainNegation(std::string relName, size_t ruleNum, const std::vector< std::string > &tuple, std::map< std::string, std::string > &bodyVariables)=0
souffle::ExplainProvenance::measureRelation
virtual std::string measureRelation(std::string relName)=0
souffle::Explain::printInfo
virtual void printInfo(const std::string &info)=0
souffle::Explain::prov
ExplainProvenance & prov
Definition: Explain.h:70
e
l j a showGridBackground &&c b raw series this eventEmitter e
Definition: htmlJsChartistMin.h:15
souffle::ExplainConfig::getExplainConfig
static ExplainConfig & getExplainConfig()
Definition: Explain.h:54
relations
std::vector< Own< Relation > > relations
Definition: ComponentInstantiation.cpp:65
souffle::ExplainProvenance::explainSubproof
virtual Own< TreeNode > explainSubproof(std::string relName, RamDomain label, size_t depthLimit)=0
i
size_t i
Definition: json11.h:663
souffle::ExplainProvenance::queryProcess
virtual void queryProcess(const std::vector< std::pair< std::string, std::vector< std::string >>> &rels)=0
Process query with given arguments.
souffle::Explain::printPrompt
virtual void printPrompt(const std::string &prompt)=0
souffle::Explain::getInput
virtual std::string getInput()=0
souffle::ExplainConfig::json
bool json
Definition: Explain.h:61
souffle::split
std::vector< std::string > split(const std::string &s, char delim, int times=-1)
utility function to split a string
Definition: ExplainProvenance.h:146
souffle::ExplainProvenance::getRule
virtual std::string getRule(std::string relName, size_t ruleNum)=0
souffle::ExplainConfig::outputStream
Own< std::ostream > outputStream
Definition: Explain.h:60
souffle::ExplainProvenance::explain
virtual Own< TreeNode > explain(std::string relName, std::vector< std::string > tuple, size_t depthLimit)=0
souffle::ExplainProvenance::getRules
virtual std::vector< std::string > getRules(const std::string &relName)=0
souffle::Explain::printTree
virtual void printTree(Own< TreeNode > tree)=0
souffle::ExplainProvenance::explainNegationGetVariables
virtual std::vector< std::string > explainNegationGetVariables(std::string relName, std::vector< std::string > args, size_t ruleNum)=0
rule
Rule & rule
Definition: Reader.h:85
souffle::Explain::printError
virtual void printError(const std::string &error)=0
souffle::Explain::parseTuple
std::pair< std::string, std::vector< std::string > > parseTuple(const std::string &str)
Parse tuple, split into relation name and values.
Definition: Explain.h:298
souffle::ExplainConfig::depthLimit
int depthLimit
Definition: Explain.h:62