\set ECHO none
\pset format unaligned

-- Cross-vertex reachability aggregations: GROUP BY over a join of a
-- reachability CTE with an untracked member relation collapses each
-- group's per-vertex reach tokens into one OR of *correlated* events
-- (the vertices share edges), which no per-vertex certificate covers.
-- The lowering detects the shape, compiles per group the certified
-- "some member reachable" circuit (the set-reachability bit folded
-- through the decomposition DP), and plants it at the canonical
-- address the aggregation will compute -- so the natural query stays
-- on the linear certified route.

SET provsql.provenance = 'boolean';

-- Diamond 1->{2,3}->4 with tail 4->5, p=.5; regions A={2,3}, B={4,5}.
-- P(A) = 1-(1-.5)^2 = .75; P(B) = P(reach 4) = 1-(1-.25)^2 = .4375
-- (5 is only reachable through 4).
CREATE TABLE btwa_edge(src int, dst int);
INSERT INTO btwa_edge VALUES (1,2),(1,3),(2,4),(3,4),(4,5);
SELECT add_provenance('btwa_edge');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM btwa_edge; END $$;
CREATE TABLE btwa_regions(node int, region text);
INSERT INTO btwa_regions VALUES (2,'A'),(3,'A'),(4,'B'),(5,'B');

CREATE TABLE btwa_r AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwa_edge e JOIN reach r ON e.src = r.node
  )
  SELECT t.region FROM reach r JOIN btwa_regions t ON r.node = t.node
  GROUP BY t.region;
CREATE TABLE btwa_p AS
  SELECT region,
         round(probability_evaluate(provenance(), 'independent')::numeric, 6)
           AS p_independent,
         round(probability_evaluate(provenance(), 'possible-worlds')::numeric, 6)
           AS p_worlds,
         (get_infos(provenance())).info1 AS certified
  FROM btwa_r GROUP BY region, provenance();
SELECT remove_provenance('btwa_p');
SELECT * FROM btwa_p ORDER BY region;
DROP TABLE btwa_p;
SELECT remove_provenance('btwa_r');
DROP TABLE btwa_r;

-- SELECT DISTINCT is provenance-identical to GROUP BY: normalised
-- before CTE lowering, so the same certified any-member gate is
-- planted and the same per-region reliability evaluates through the
-- linear route (certified, matching the GROUP BY case exactly).
CREATE TABLE btwa_rd AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwa_edge e JOIN reach r ON e.src = r.node
  )
  SELECT DISTINCT t.region FROM reach r JOIN btwa_regions t ON r.node = t.node;
CREATE TABLE btwa_pd AS
  SELECT region,
         round(probability_evaluate(provenance(), 'independent')::numeric, 6)
           AS p_independent,
         round(probability_evaluate(provenance(), 'possible-worlds')::numeric, 6)
           AS p_worlds,
         (get_infos(provenance())).info1 AS certified
  FROM btwa_rd GROUP BY region, provenance();
SELECT remove_provenance('btwa_pd');
SELECT * FROM btwa_pd ORDER BY region;
DROP TABLE btwa_pd;
SELECT remove_provenance('btwa_rd');
DROP TABLE btwa_rd;

-- A deterministic filter over the *member* relation's own columns
-- restricts which members participate in each group (like the edge
-- filters restrict the edges -- it carries no provenance), and is
-- pushed into the member gathering: still planted, still certified.
CREATE TABLE btwa_kinds(node int, region text, kind text);
INSERT INTO btwa_kinds VALUES
  (2,'A','hospital'),(3,'A','depot'),(4,'B','hospital'),(5,'B','hospital');
CREATE TABLE btwa_rf AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwa_edge e JOIN reach r ON e.src = r.node
  )
  SELECT t.region FROM reach r JOIN btwa_kinds t ON r.node = t.node
  WHERE t.kind = 'hospital'
  GROUP BY t.region;
CREATE TABLE btwa_pf AS
  SELECT region,
         round(probability_evaluate(provenance(), 'independent')::numeric, 6)
           AS p_independent,
         round(probability_evaluate(provenance(), 'possible-worlds')::numeric, 6)
           AS p_worlds,
         (get_infos(provenance())).info1 AS certified
  FROM btwa_rf GROUP BY region, provenance();
SELECT remove_provenance('btwa_pf');
-- Region A loses the depot (node 3): just {2}, P = .5 (a single-member
-- group passes its per-vertex token through, behind the assumption
-- wrapper, so info1 = 0 there); region B keeps {4,5}, P = .4375,
-- planted and certified.
SELECT * FROM btwa_pf ORDER BY region;
DROP TABLE btwa_pf;
SELECT remove_provenance('btwa_rf');
DROP TABLE btwa_rf;
DROP TABLE btwa_kinds;

-- A *tracked* member relation makes the aggregated tokens per-row
-- products: nothing is planted, the generic path stays correct.
CREATE TABLE btwa_tracked(node int, region text);
INSERT INTO btwa_tracked VALUES (2,'A'),(3,'A');
SELECT add_provenance('btwa_tracked');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM btwa_tracked; END $$;
CREATE TABLE btwa_tr AS
  WITH RECURSIVE reach(node) AS (
      SELECT 1
    UNION
      SELECT e.dst FROM btwa_edge e JOIN reach r ON e.src = r.node
  )
  SELECT t.region FROM reach r JOIN btwa_tracked t ON r.node = t.node
  GROUP BY t.region;
CREATE TABLE btwa_tp AS
  SELECT region,
         round(probability_evaluate(provenance(), 'possible-worlds')::numeric, 6)
           AS p_worlds
  FROM btwa_tr GROUP BY region, provenance();
SELECT remove_provenance('btwa_tp');
-- P = 1 - (1 - .5*.5)^2 = .4375 (per-vertex reach times region-row).
SELECT * FROM btwa_tp ORDER BY region;
DROP TABLE btwa_tp;
SELECT remove_provenance('btwa_tr');
DROP TABLE btwa_tr;
SELECT remove_provenance('btwa_tracked');
DROP TABLE btwa_tracked;

SET provsql.provenance = 'semiring';
SELECT remove_provenance('btwa_edge');
DROP TABLE btwa_edge;
DROP TABLE btwa_regions;
RESET provsql.provenance;
