ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
DotCircuit.cpp
Go to the documentation of this file.
1/**
2 * @file DotCircuit.cpp
3 * @brief DotCircuit method implementations and GraphViz rendering.
4 *
5 * Implements:
6 * - @c DotCircuit::addGate(): allocate a gate and extend the @c desc vector.
7 * - @c DotCircuit::setGate(const uuid&, DotGate): create a gate by UUID.
8 * - @c DotCircuit::setGate(const uuid&, DotGate, std::string): create a gate
9 * with a label string stored in @c desc.
10 * - @c DotCircuit::toString(): return the description string for a gate.
11 * - @c DotCircuit::render(): produce a complete GraphViz @c digraph string
12 * with semiring symbols (⊗, ⊕, ⊖, δ) as node labels and the
13 * provenance token UUIDs as edge labels for input gates.
14 */
15#include "DotCircuit.h"
16#include <type_traits>
17
18extern "C"
19{
20#include "provsql_utils.h"
21#include <unistd.h>
22}
23
24#include <cassert>
25#include <string>
26#include <fstream>
27#include <sstream>
28#include <cstdlib>
29
30// Has to be redefined because of name hiding
32{
33 auto id = Circuit::setGate(u, type);
34 if(type == DotGate::IN)
35 inputs.insert(id);
36 return id;
37}
38
39gate_t DotCircuit::setGate(const uuid &u, DotGate type, std::string d)
40{
41 auto id = setGate(u, type);
42 desc[static_cast<std::underlying_type<gate_t>::type>(id)] = d;
43 return id;
44}
45
47{
48 auto id=Circuit::addGate();
49 desc.push_back("");
50 return id;
51}
52
53//Outputs the gate in Graphviz dot format
54std::string DotCircuit::toString(gate_t) const
55{
56 std::string op;
57 std::string result="digraph circuit{\n graph [rankdir=UD] ;\n";
58
59 //looping through the gates
60 //eliminating the minusr and minusl gates
61 unsigned i = 0;
62 for (auto g : gates)
63 {
64 if (g != DotGate::OMINUSR && g != DotGate::OMINUSL)
65 {
66 result += std::to_string(i) + " [label=";
67 switch (g)
68 {
69 case DotGate::IN:
70 result += "\"" + desc[i] + "\"";
71 break;
72 case DotGate::OMINUS:
73 result += "\"⊖\"";
74 break;
76 result += "\"?\"";
77 break;
78 case DotGate::OTIMES:
79 result += "\"⊗\"";
80 break;
81 case DotGate::OPLUS:
82 result += "\"⊕\"";
83 break;
84 case DotGate::DELTA:
85 result += "\"δ\"";
86 break;
87 case DotGate::EQ:
88 result += "\"" + desc[i] + "\"";
89 break;
91 result += "\"Π" + desc[i] + "\"";
92 break;
95 break;
96 }
97 if(i==0)
98 result+=",shape=\"double\"";
99 result+="];\n";
100 }
101 i++;
102 }
103
104 //looping through the gates and their wires
105 for(i=0; i<wires.size(); ++i) {
106 if(gates[i] != DotGate::OMINUSR && gates[i] != DotGate::OMINUSL) {
107 std::unordered_map<gate_t, unsigned> number_gates;
108 for(auto s: wires[i]) {
109 if(number_gates.find(s)!=number_gates.end()) {
110 number_gates[s] = number_gates[s]+1;
111 }
112 else
113 {
114 number_gates[s] = 1;
115 }
116 }
117 for(auto [s,n]: number_gates)
118 {
120 for(auto t: getWires(s)) {
121 result += std::to_string(i)+" -> "+to_string(t);
123 result += " [label=\"R\"];\n";
124 else
125 result += " [label=\"L\"];\n";
126 }
127 }
128 else {
129 result += std::to_string(i)+" -> "+to_string(s);
130 if(n==1) {
131 result += ";\n";
132 }
133 else
134 {
135 result += " [label=\"" + std::to_string(n) + "\"];\n";
136 }
137 }
138 }
139 }
140 }
141 return result + "}";
142}
143
144std::string DotCircuit::render() const {
145 //Writing dot to a temporary file
146 int fd;
147 char cfilename[] = "/tmp/provsqlXXXXXX";
148 fd = mkstemp(cfilename);
149 close(fd);
150 std::string filename=cfilename, outfilename=filename+".out";
151
152 std::ofstream ofs(filename.c_str());
153 ofs << toString(gate_t{0});
154 ofs.close();
155
156 //Executing the Graphviz dot renderer through graph-easy for ASCII
157 //output
158 std::string cmdline="graph-easy --as=boxart --output="+outfilename+" "+filename;
159
160 int retvalue = system(cmdline.c_str());
161
162 if(provsql_verbose<20) {
163 if(unlink(filename.c_str())) {
164 throw CircuitException("Error removing "+filename);
165 }
166 }
167
168 if(retvalue)
169 throw CircuitException("Error executing graph-easy");
170
171 std::ifstream ifs(outfilename.c_str());
172 std::string str((std::istreambuf_iterator<char>(ifs)),
173 std::istreambuf_iterator<char>());
174
175 if(provsql_verbose<20) {
176 if(unlink(outfilename.c_str())) {
177 throw CircuitException("Error removing "+outfilename);
178 }
179 }
180
181 return str;
182}
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:48
std::string to_string(gate_t g)
Convert a gate_t to its decimal string representation.
Definition Circuit.h:249
Provenance circuit variant that renders to GraphViz DOT format.
DotGate
Gate types for a DOT visualisation circuit.
Definition DotCircuit.h:42
@ PROJECT
Projection gate.
@ OPLUS
Semiring plus (⊕)
@ EQ
Equijoin gate.
@ OMINUS
Semiring monus (⊖), full.
@ OMINUSL
Monus, left child only.
@ OMINUSR
Monus, right child only.
@ DELTA
δ-semiring operator
@ IN
Input (variable) gate.
@ UNDETERMINED
Placeholder gate not yet assigned a type.
@ OTIMES
Semiring times (⊗)
Exception type thrown by circuit operations on invalid input.
Definition Circuit.h:205
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
Definition Circuit.h:139
DotGate getGateType(gate_t g) const
Return the type of gate g.
Definition Circuit.h:129
virtual gate_t setGate(const uuid &u, gateType type)
Create or update the gate associated with UUID u.
Definition Circuit.hpp:73
std::vector< DotGate > gates
Gate type for each gate.
Definition Circuit.h:70
std::vector< std::vector< gate_t > > wires
Child wire lists for each gate.
Definition Circuit.h:71
virtual gate_t addGate()
Allocate a new gate with a default-initialised type.
Definition Circuit.hpp:56
virtual std::string toString(gate_t g) const override
Return a textual description of gate g for debugging.
gate_t addGate() override
Allocate a new gate with a default-initialised type.
std::set< gate_t > inputs
Input gate IDs (rendered as leaf nodes)
Definition DotCircuit.h:63
gate_t setGate(const uuid &u, DotGate type) override
Create or update the gate associated with UUID u.
std::string render() const
Render the entire circuit as a GraphViz DOT digraph string.
std::vector< std::string > desc
Per-gate label strings (indexed by gate ID)
Definition DotCircuit.h:64
int provsql_verbose
Verbosity level; controlled by the provsql.verbose_level GUC.
Definition provsql.c:66
Core types, constants, and utilities shared across ProvSQL.