\set ECHO none
\pset format unaligned

-- Min-cost reachability through the decomposition-aligned compilation:
-- under the 'absorptive' provenance class the reachability route's
-- certified d-DNNF tokens evaluate exactly in any absorptive semiring
-- (the deterministic world enumeration surfaces every minimal
-- derivation support -- here, every path -- and absorption erases the
-- rest), so sr_tropical(..., nonnegative => true) computes
-- single-source min-cost in time linear in the circuit, cyclic data
-- included.  No dedicated evaluation rule: the certificate's
-- monus(one, edge) negations natively evaluate to the tropical one on
-- positively-priced edges, and the worlds a free (cost-0) edge's
-- negation kills are dominated by their supersets at equal cost.

SET provsql.provenance = 'absorptive';

-- Cost-0 edge: 1->2 free, 2->3 costs 5, direct 1->3 costs 6, free
-- cycle edge 3->1.  Min cost to 3 is 5, through the free edge.
CREATE TABLE btwt_edge(src int, dst int, cost float8);
INSERT INTO btwt_edge VALUES (1,2,0),(2,3,5),(1,3,6),(3,1,0);
SELECT add_provenance('btwt_edge');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM btwt_edge; END $$;
SELECT create_provenance_mapping('btwt_cost', 'btwt_edge', 'cost');
CREATE TABLE btwt_r AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwt_edge e JOIN reach r ON e.src = r.node
  )
  SELECT node, provenance() pv FROM reach;
SELECT remove_provenance('btwt_r');
SELECT node, sr_tropical(pv, 'btwt_cost', nonnegative => true) AS min_cost
FROM btwt_r ORDER BY node;
DROP TABLE btwt_r;
DROP TABLE btwt_edge;

-- Hop-bounded min-cost (constrained shortest path): unit-cost chain
-- 1->2->3->4->5 against a 1-hop shortcut 1->5 of cost 10.  Within 2
-- hops the cheap chain is out of reach: min cost to 5 is 10, and node
-- 4 (3 hops away) is not reported at all.
CREATE TABLE btwt_chain(src int, dst int, cost float8);
INSERT INTO btwt_chain VALUES (1,2,1),(2,3,1),(3,4,1),(4,5,1),(1,5,10);
SELECT add_provenance('btwt_chain');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM btwt_chain; END $$;
SELECT create_provenance_mapping('btwt_chain_cost', 'btwt_chain', 'cost');
CREATE TABLE btwt_h AS
  WITH RECURSIVE reach(node, hops) AS (
      SELECT 1, 0
    UNION
      SELECT e.dst, r.hops + 1 FROM btwt_chain e JOIN reach r ON e.src = r.node
      WHERE r.hops < 2
  )
  SELECT node FROM reach GROUP BY node;
CREATE TABLE btwt_h2 AS
  SELECT node, sr_tropical(provenance(), 'btwt_chain_cost',
                           nonnegative => true) AS min_cost_2hops
  FROM btwt_h GROUP BY node, provenance();
SELECT remove_provenance('btwt_h2');
SELECT * FROM btwt_h2 ORDER BY node;
DROP TABLE btwt_h2;
SELECT remove_provenance('btwt_h');
DROP TABLE btwt_h;
DROP TABLE btwt_chain;

-- Multi-length vertices land on the planted certified canonical:
-- cyclic triangle 1->2 (cost 3), 2->3 (4), 3->1 (1), within 4 hops --
-- nodes 1 and 2 achieve two walk lengths each (the cycle pumps
-- lengths), node 3 a single one.  Reliability and min-cost evaluate
-- on the same tokens.
CREATE TABLE btwt_tri(src int, dst int, cost float8);
INSERT INTO btwt_tri VALUES (1,2,3),(2,3,4),(3,1,1);
SELECT add_provenance('btwt_tri');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM btwt_tri; END $$;
SELECT create_provenance_mapping('btwt_tri_cost', 'btwt_tri', 'cost');
CREATE TABLE btwt_t AS
  WITH RECURSIVE reach(node, hops) AS (
      SELECT 1, 0
    UNION
      SELECT e.dst, r.hops + 1 FROM btwt_tri e JOIN reach r ON e.src = r.node
      WHERE r.hops < 4
  )
  SELECT node FROM reach GROUP BY node;
CREATE TABLE btwt_t2 AS
  SELECT node, round(probability_evaluate(provenance())::numeric, 6) AS prob,
         sr_tropical(provenance(), 'btwt_tri_cost', nonnegative => true)
           AS min_cost,
         get_gate_type(provenance()) AS root_type
  FROM btwt_t GROUP BY node, provenance();
SELECT remove_provenance('btwt_t2');
SELECT * FROM btwt_t2 ORDER BY node;
DROP TABLE btwt_t2;
SELECT remove_provenance('btwt_t');
DROP TABLE btwt_t;
DROP TABLE btwt_tri;

-- Cross-vertex region min-cost: the GROUP BY over a join with an
-- untracked member relation lands on the planted any-member circuit,
-- giving the min cost of reaching each region.  Diamond
-- 1->{2,3}->4->5: region A = {2,3} costs min(5,2) = 2, region B =
-- {4,5} costs min(5+1, 2+9) = 6.
CREATE TABLE btwt_dia(src int, dst int, cost float8);
INSERT INTO btwt_dia VALUES (1,2,5),(1,3,2),(2,4,1),(3,4,9),(4,5,1);
SELECT add_provenance('btwt_dia');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM btwt_dia; END $$;
SELECT create_provenance_mapping('btwt_dia_cost', 'btwt_dia', 'cost');
CREATE TABLE btwt_regions(node int, region text);
INSERT INTO btwt_regions VALUES (2,'A'),(3,'A'),(4,'B'),(5,'B');
CREATE TABLE btwt_g AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwt_dia e JOIN reach r ON e.src = r.node
  )
  SELECT t.region FROM reach r JOIN btwt_regions t ON r.node = t.node
  GROUP BY t.region;
CREATE TABLE btwt_g2 AS
  SELECT region,
         sr_tropical(provenance(), 'btwt_dia_cost', nonnegative => true)
           AS min_cost,
         round(probability_evaluate(provenance(), 'independent')::numeric, 6)
           AS prob,
         (get_infos(provenance())).info1 AS certified
  FROM btwt_g GROUP BY region, provenance();
SELECT remove_provenance('btwt_g2');
SELECT * FROM btwt_g2 ORDER BY region;
DROP TABLE btwt_g2;
-- Counting refuses the routed tokens, through the planted canonical
-- as well: the compiled circuit only represents the absorptive
-- quotient of the recursive provenance.
SELECT sr_counting(provenance(), 'btwt_dia_cost') FROM btwt_g
GROUP BY region, provenance();
SELECT remove_provenance('btwt_g');
DROP TABLE btwt_g;
DROP TABLE btwt_regions;
DROP TABLE btwt_dia;

-- Every absorptive semiring reads the same routed circuits exactly,
-- not just min-plus: most-reliable path (Viterbi), widest path
-- (max-min over an enum), fuzzy best path (Lukasiewicz), and temporal
-- reachability (interval union, whose monus is a genuine set
-- difference).  Diamond 1->{2,3}->4->5 plus a never-valid cycle edge
-- 5->1; edge 4->5 is fully reliable / top capacity / always valid, so
-- its negation hits each semiring's NOT-kill corner (the killed
-- worlds are dominated by their supersets).
SET TIME ZONE 'UTC';
SET datestyle = 'iso';
CREATE TYPE btwt_cap AS ENUM ('low','medium','high');
CREATE TABLE btwt_net(src int, dst int, rel float8, cap btwt_cap,
                      valid tstzmultirange);
INSERT INTO btwt_net VALUES
  (1,2, 0.9,  'high',   '{[2020-01-01,2020-10-01)}'),
  (2,4, 0.8,  'medium', '{[2020-05-01,2021-08-01)}'),
  (1,3, 0.5,  'low',    '{[2020-01-01,2020-03-01)}'),
  (3,4, 0.99, 'high',   '{[2020-02-01,2020-08-01)}'),
  (4,5, 1.0,  'high',   '{(,)}'),
  (5,1, 0.5,  'low',    '{}');
SELECT add_provenance('btwt_net');
DO $$ BEGIN PERFORM set_prob(provenance(), rel) FROM btwt_net; END $$;
SELECT create_provenance_mapping('btwt_rel', 'btwt_net', 'rel');
SELECT create_provenance_mapping('btwt_cap_map', 'btwt_net', 'cap');
SELECT create_provenance_mapping('btwt_valid', 'btwt_net', 'valid');
CREATE TABLE btwt_n AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwt_net e JOIN reach r ON e.src = r.node
  )
  SELECT node, provenance() pv FROM reach;
SELECT remove_provenance('btwt_n');
-- To 4: most reliable = max(.9*.8, .5*.99) = .72; widest =
-- max(min(high,medium), min(low,high)) = medium; fuzzy =
-- max(.9+.8-1, .5+.99-1) = .7; valid = [05-01,10-01) U [02-01,03-01).
-- To 5: the fully-reliable / top / always-valid edge is neutral.
SELECT node,
       round(sr_viterbi(pv, 'btwt_rel')::numeric, 6) AS most_reliable,
       sr_maxmin(pv, 'btwt_cap_map', 'low'::btwt_cap) AS widest,
       round(sr_lukasiewicz(pv, 'btwt_rel')::numeric, 6) AS fuzzy,
       sr_temporal(pv, 'btwt_valid') AS valid
FROM btwt_n WHERE node IN (4, 5) ORDER BY node;
DROP TABLE btwt_n;
DROP TABLE btwt_net;
DROP TABLE btwt_cap_map;
DROP TYPE btwt_cap;

SET provsql.provenance = 'semiring';
RESET provsql.provenance;
