16#include <unordered_set>
43#include <unordered_map>
73 std::unordered_map<gate_t, gate_t> redirect;
86 for (std::size_t i = 0; i < n; ++i) {
87 auto g =
static_cast<gate_t>(i);
92 std::vector<gate_t> kept;
93 kept.reserve(
wires.size());
95 if (gc.
getGateType(c) != identity) kept.push_back(c);
97 if (kept.size() !=
wires.size()) {
98 wires = std::move(kept);
119 std::unordered_map<gate_t, gate_t> subst;
120 for (std::size_t i = 0; i < n; ++i) {
121 auto g =
static_cast<gate_t>(i);
122 if (redirect.count(g))
continue;
127 bool absorbed =
false;
135 if (absorbed)
continue;
142 for (
auto &kv : subst) {
144 while (subst.count(cur) || redirect.count(cur))
145 cur = subst.count(cur) ? subst[cur] : redirect[cur];
154 if (!subst.empty()) {
155 for (std::size_t i = 0; i < n; ++i) {
158 auto it = subst.find(w);
159 if (it != subst.end()) {
165 for (
const auto &kv : subst) redirect[kv.first] = kv.second;
175 if (!redirect.empty()) {
176 for (
auto &kv : redirect) {
178 while (redirect.count(cur)) cur = redirect[cur];
181 for (
const auto &kv : redirect) {
182 gate_t g = kv.first, target = kv.second;
199 for (std::size_t i = 0; i < n; ++i) {
200 auto g =
static_cast<gate_t>(i);
209 bool absorptive_rule_fired =
false;
210 bool boolean_rule_fired =
false;
218 std::unordered_set<gate_t> seen;
219 std::vector<gate_t> deduped;
220 deduped.reserve(
wires.size());
222 if (seen.insert(c).second) deduped.push_back(c);
224 if (deduped.size() !=
wires.size()) {
225 wires = std::move(deduped);
227 absorptive_rule_fired =
true;
229 boolean_rule_fired =
true;
238 bool has_one =
false;
244 gc.
setWires(g, std::vector<gate_t>{});
247 absorptive_rule_fired =
true;
272 const auto &wires_now = gc.
getWires(g);
273 if (wires_now.size() >= 2) {
274 std::unordered_set<gate_t> sibling_set(wires_now.begin(),
276 std::vector<gate_t> kept;
277 kept.reserve(wires_now.size());
278 bool dropped =
false;
279 for (
gate_t c : wires_now) {
283 if (w != c && sibling_set.count(w)) {
288 if (absorb) { dropped =
true;
continue; }
295 absorptive_rule_fired =
true;
297 boolean_rule_fired =
true;
302 if (absorptive_rule_fired)
304 if (boolean_rule_fired)
306 if (absorptive_rule_fired || boolean_rule_fired)
gate_t
Strongly-typed gate identifier.
Semiring-agnostic in-memory provenance circuit.
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
gateType getGateType(gate_t g) const
Return the type of gate g.
std::unordered_map< gate_t, uuid > id2uuid
virtual gate_t setGate(const uuid &u, gateType type)
Create or update the gate associated with UUID u.
std::unordered_map< uuid, gate_t > uuid2id
void setGateType(gate_t g, gateType t)
Update the type of an existing gate.
std::vector< std::vector< gate_t > > wires
std::vector< gate_t >::size_type getNbGates() const
Return the total number of gates in the circuit.
virtual gate_t addGate()
Allocate a new gate with a default-initialised type.
In-memory provenance circuit with semiring-generic evaluation.
void setWires(gate_t g, std::vector< gate_t > w)
Replace the wires of g with w.
std::map< gate_t, std::pair< unsigned, unsigned > > infos
Per-gate (info1, info2) annotations.
void markAbsorptiveAssumed(gate_t g)
Mark gate g as absorptive-assumed (in-memory side band).
bool foldSemiringIdentities()
Drop semiring identity wires and collapse single-wire gate_times / gate_plus to their lone non-identi...
void foldAbsorptiveIdentities()
Absorptive-rules-only variant of foldBooleanIdentities(): the joint fixpoint of the absorptive fold r...
std::map< gate_t, std::string > extra
Per-gate string extras.
gate_t addGate() override
Allocate a new gate with a default-initialised type.
std::set< gate_t > inputs
Set of input (leaf) gate IDs.
std::set< gate_t > absorptive_assumed_gates
Side-band absorptive-assumption marker set by the absorptive fold rules (plus-idempotence,...
std::vector< double > prob
Per-gate probability values.
gate_t setGate(gate_type type) override
Allocate a new gate with type type and no UUID.
void markBooleanAssumed(gate_t g)
Mark gate g as Boolean-assumed (in-memory side band).
std::set< gate_t > boolean_assumed_gates
Side-band Boolean-assumption marker set by the Boolean-only fold rules ; an evaluator visiting a gate...
bool applyFoldRuleSweep(bool boolean_level)
One pass of the fold rules over every gate_plus / gate_times.
void foldBooleanIdentities()
Apply the Boolean-only AND the absorptive simplification rules to gate_plus and gate_times,...