souffle  2.0.2-371-g6315b36
ExplainProvenance.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2017, 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 ExplainProvenance.h
12  *
13  * Abstract class for implementing an instance of the explain interface for provenance
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "souffle/RamTypes.h"
21 #include "souffle/SymbolTable.h"
25 #include <algorithm>
26 #include <cassert>
27 #include <cstdio>
28 #include <map>
29 #include <memory>
30 #include <sstream>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 namespace souffle {
36 class TreeNode;
37 
38 /** Equivalence class for variables in query command */
39 class Equivalence {
40 public:
41  /** Destructor */
42  ~Equivalence() = default;
43 
44  /**
45  * Constructor for Equvialence class
46  * @param t, type of the variable
47  * @param s, symbol of the variable
48  * @param idx, first occurence of the variable
49  * */
50  Equivalence(char t, std::string s, std::pair<size_t, size_t> idx) : type(t), symbol(std::move(s)) {
51  indices.push_back(idx);
52  }
53 
54  /** Copy constructor */
55  Equivalence(const Equivalence& o) = default;
56 
57  /** Copy assignment operator */
58  Equivalence& operator=(const Equivalence& o) = default;
59 
60  /** Add index at the end of indices vector */
61  void push_back(std::pair<size_t, size_t> idx) {
62  indices.push_back(idx);
63  }
64 
65  /** Verify if elements at the indices are equivalent in the given product */
66  bool verify(const std::vector<tuple>& product) const {
67  for (size_t i = 1; i < indices.size(); ++i) {
68  if (product[indices[i].first][indices[i].second] !=
69  product[indices[i - 1].first][indices[i - 1].second]) {
70  return false;
71  }
72  }
73  return true;
74  }
75 
76  /** Extract index of the first occurrence of the varible */
77  const std::pair<size_t, size_t>& getFirstIdx() const {
78  return indices[0];
79  }
80 
81  /** Get indices of equivalent variables */
82  const std::vector<std::pair<size_t, size_t>>& getIndices() const {
83  return indices;
84  }
85 
86  /** Get type of the variable of the equivalence class,
87  * 'i' for RamSigned, 's' for symbol
88  * 'u' for RamUnsigned, 'f' for RamFloat
89  */
90  char getType() const {
91  return type;
92  }
93 
94  /** Get the symbol of variable */
95  const std::string& getSymbol() const {
96  return symbol;
97  }
98 
99 private:
100  char type;
101  std::string symbol;
102  std::vector<std::pair<size_t, size_t>> indices;
103 };
104 
105 /** Constant constraints for values in query command */
107 public:
108  /** Constructor */
109  ConstConstraint() = default;
110 
111  /** Destructor */
112  ~ConstConstraint() = default;
113 
114  /** Add constant constraint at the end of constConstrs vector */
115  void push_back(std::pair<std::pair<size_t, size_t>, RamDomain> constr) {
116  constConstrs.push_back(constr);
117  }
118 
119  /** Verify if the query product satisfies constant constraint */
120  bool verify(const std::vector<tuple>& product) const {
121  return std::all_of(constConstrs.begin(), constConstrs.end(), [&product](auto constr) {
122  return product[constr.first.first][constr.first.second] == constr.second;
123  });
124  }
125 
126  /** Get the constant constraint vector */
127  std::vector<std::pair<std::pair<size_t, size_t>, RamDomain>>& getConstraints() {
128  return constConstrs;
129  }
130 
131  const std::vector<std::pair<std::pair<size_t, size_t>, RamDomain>>& getConstraints() const {
132  return constConstrs;
133  }
134 
135 private:
136  std::vector<std::pair<std::pair<size_t, size_t>, RamDomain>> constConstrs;
137 };
138 
139 /** utility function to split a string */
140 inline std::vector<std::string> split(const std::string& s, char delim, int times = -1) {
141  std::vector<std::string> v;
142  std::stringstream ss(s);
143  std::string item;
144 
145  while ((times > 0 || times <= -1) && std::getline(ss, item, delim)) {
146  v.push_back(item);
147  times--;
148  }
149 
150  if (ss.peek() != EOF) {
151  std::string remainder;
152  std::getline(ss, remainder);
153  v.push_back(remainder);
154  }
155 
156  return v;
157 }
158 
159 class ExplainProvenance {
160 public:
161  ExplainProvenance(SouffleProgram& prog) : prog(prog), symTable(prog.getSymbolTable()) {}
162  virtual ~ExplainProvenance() = default;
163 
164  virtual void setup() = 0;
165 
166  virtual Own<TreeNode> explain(std::string relName, std::vector<std::string> tuple, size_t depthLimit) = 0;
167 
168  virtual Own<TreeNode> explainSubproof(std::string relName, RamDomain label, size_t depthLimit) = 0;
169 
170  virtual std::vector<std::string> explainNegationGetVariables(
171  std::string relName, std::vector<std::string> args, size_t ruleNum) = 0;
172 
173  virtual Own<TreeNode> explainNegation(std::string relName, size_t ruleNum,
174  const std::vector<std::string>& tuple, std::map<std::string, std::string>& bodyVariables) = 0;
175 
176  virtual std::string getRule(std::string relName, size_t ruleNum) = 0;
177 
178  virtual std::vector<std::string> getRules(const std::string& relName) = 0;
179 
180  virtual std::string measureRelation(std::string relName) = 0;
181 
182  virtual void printRulesJSON(std::ostream& os) = 0;
183 
184  /**
185  * Process query with given arguments
186  * @param rels, vector of relation, argument pairs
187  * */
188  virtual void queryProcess(const std::vector<std::pair<std::string, std::vector<std::string>>>& rels) = 0;
189 
190 protected:
193 
194  std::vector<RamDomain> argsToNums(
195  const std::string& relName, const std::vector<std::string>& args) const {
196  std::vector<RamDomain> nums;
197 
198  auto rel = prog.getRelation(relName);
199  if (rel == nullptr) {
200  return nums;
201  }
202 
203  for (size_t i = 0; i < args.size(); i++) {
204  nums.push_back(valueRead(rel->getAttrType(i)[0], args[i]));
205  }
206 
207  return nums;
208  }
209 
210  /**
211  * Decode arguments from their ram representation and return as strings.
212  **/
213  std::vector<std::string> decodeArguments(
214  const std::string& relName, const std::vector<RamDomain>& nums) const {
215  std::vector<std::string> args;
216 
217  auto rel = prog.getRelation(relName);
218  if (rel == nullptr) {
219  return args;
220  }
221 
222  for (size_t i = 0; i < nums.size(); i++) {
223  args.push_back(valueShow(rel->getAttrType(i)[0], nums[i]));
224  }
225 
226  return args;
227  }
228 
229  std::string valueShow(const char type, const RamDomain value) const {
230  switch (type) {
231  case 'i': return tfm::format("%d", ramBitCast<RamSigned>(value));
232  case 'u': return tfm::format("%d", ramBitCast<RamUnsigned>(value));
233  case 'f': return tfm::format("%f", ramBitCast<RamFloat>(value));
234  case 's': return tfm::format("\"%s\"", symTable.resolve(value));
235  case 'r': return tfm::format("record #%d", value);
236  default: fatal("unhandled type attr code");
237  }
238  }
239 
240  RamDomain valueRead(const char type, const std::string& value) const {
241  switch (type) {
242  case 'i': return ramBitCast(RamSignedFromString(value));
243  case 'u': return ramBitCast(RamUnsignedFromString(value));
244  case 'f': return ramBitCast(RamFloatFromString(value));
245  case 's':
246  assert(2 <= value.size() && value[0] == '"' && value.back() == '"');
247  return symTable.lookup(value.substr(1, value.size() - 2));
248  case 'r': fatal("not implemented");
249  default: fatal("unhandled type attr code");
250  }
251  }
252 };
253 
254 } // end of namespace souffle
souffle::ExplainProvenance::setup
virtual void setup()=0
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::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::ExplainProvenance::measureRelation
virtual std::string measureRelation(std::string relName)=0
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::ConstConstraint::verify
bool verify(const std::vector< tuple > &product) const
Verify if the query product satisfies constant constraint.
Definition: ExplainProvenance.h:126
souffle::Equivalence::getFirstIdx
const std::pair< size_t, size_t > & getFirstIdx() const
Extract index of the first occurrence of the varible.
Definition: ExplainProvenance.h:83
souffle::RamDomain
int32_t RamDomain
Definition: RamTypes.h:56
tinyformat::format
void format(std::ostream &out, const char *fmt)
Definition: tinyformat.h:1089
souffle::Equivalence::type
char type
Definition: ExplainProvenance.h:106
souffle::Equivalence::getSymbol
const std::string & getSymbol() const
Get the symbol of variable.
Definition: ExplainProvenance.h:101
SymbolTable.h
souffle::ConstConstraint::ConstConstraint
ConstConstraint()=default
Constructor.
souffle::ExplainProvenance::prog
SouffleProgram & prog
Definition: ExplainProvenance.h:197
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
MiscUtil.h
souffle::ConstConstraint
Constant constraints for values in query command.
Definition: ExplainProvenance.h:112
tinyformat.h
souffle::ExplainProvenance::explainSubproof
virtual Own< TreeNode > explainSubproof(std::string relName, RamDomain label, size_t depthLimit)=0
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::Equivalence::operator=
Equivalence & operator=(const Equivalence &o)=default
Copy assignment operator.
souffle::SouffleProgram
Abstract base class for generated Datalog programs.
Definition: SouffleInterface.h:693
souffle::Equivalence::getIndices
const std::vector< std::pair< size_t, size_t > > & getIndices() const
Get indices of equivalent variables.
Definition: ExplainProvenance.h:88
souffle::times
detail::multiplying_printer< T > times(const T &value, unsigned num)
A utility printing a given value multiple times.
Definition: StreamUtil.h:322
i
size_t i
Definition: json11.h:663
souffle::ExplainProvenance::valueShow
std::string valueShow(const char type, const RamDomain value) const
Definition: ExplainProvenance.h:235
souffle::Equivalence::Equivalence
Equivalence(char t, std::string s, std::pair< size_t, size_t > idx)
Constructor for Equvialence class.
Definition: ExplainProvenance.h:56
souffle::ExplainProvenance::queryProcess
virtual void queryProcess(const std::vector< std::pair< std::string, std::vector< std::string >>> &rels)=0
Process query with given arguments.
StringUtil.h
o
var o
Definition: htmlJsChartistMin.h:15
souffle::ExplainProvenance::~ExplainProvenance
virtual ~ExplainProvenance()=default
souffle::ExplainProvenance::valueRead
RamDomain valueRead(const char type, const std::string &value) const
Definition: ExplainProvenance.h:246
souffle::SymbolTable
Definition: SymbolTable.h:48
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::ConstConstraint::getConstraints
std::vector< std::pair< std::pair< size_t, size_t >, RamDomain > > & getConstraints()
Get the constant constraint vector.
Definition: ExplainProvenance.h:133
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::Equivalence
Equivalence class for variables in query command.
Definition: ExplainProvenance.h:45
souffle::ConstConstraint::~ConstConstraint
~ConstConstraint()=default
Destructor.
souffle::Equivalence::push_back
void push_back(std::pair< size_t, size_t > idx)
Add index at the end of indices vector.
Definition: ExplainProvenance.h:67
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::Equivalence::symbol
std::string symbol
Definition: ExplainProvenance.h:107
souffle::ExplainProvenance::printRulesJSON
virtual void printRulesJSON(std::ostream &os)=0
souffle::ExplainProvenance::explain
virtual Own< TreeNode > explain(std::string relName, std::vector< std::string > tuple, size_t depthLimit)=0
souffle::all_of
bool all_of(const Container &c, UnaryPredicate p)
A generic test checking whether all elements within a container satisfy a certain predicate.
Definition: FunctionalUtil.h:110
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::ExplainProvenance::ExplainProvenance
ExplainProvenance(SouffleProgram &prog)
Definition: ExplainProvenance.h:167
std
Definition: Brie.h:3053
souffle::ConstConstraint::push_back
void push_back(std::pair< std::pair< size_t, size_t >, RamDomain > constr)
Add constant constraint at the end of constConstrs vector.
Definition: ExplainProvenance.h:121
souffle::ExplainProvenance::getRules
virtual std::vector< std::string > getRules(const std::string &relName)=0
souffle::Equivalence::verify
bool verify(const std::vector< tuple > &product) const
Verify if elements at the indices are equivalent in the given product.
Definition: ExplainProvenance.h:72
souffle::ExplainProvenance::explainNegationGetVariables
virtual std::vector< std::string > explainNegationGetVariables(std::string relName, std::vector< std::string > args, size_t ruleNum)=0
RamTypes.h
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
souffle::ConstConstraint::constConstrs
std::vector< std::pair< std::pair< size_t, size_t >, RamDomain > > constConstrs
Definition: ExplainProvenance.h:142
souffle
Definition: AggregateOp.h:25
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::Equivalence::getType
char getType() const
Get type of the variable of the equivalence class, 'i' for RamSigned, 's' for symbol 'u' for RamUnsig...
Definition: ExplainProvenance.h:96
souffle::Equivalence::indices
std::vector< std::pair< size_t, size_t > > indices
Definition: ExplainProvenance.h:108
souffle::RamFloatFromString
RamFloat RamFloatFromString(const std::string &str, std::size_t *position=nullptr)
Converts a string to a RamFloat.
Definition: StringUtil.h:93
souffle::Equivalence::~Equivalence
~Equivalence()=default
Destructor.
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::tuple
Defines a tuple for the OO interface such that relations with varying columns can be accessed.
Definition: SouffleInterface.h:443
SouffleInterface.h
std::type
ElementType type
Definition: span.h:640
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336