\set ECHO none \pset format unaligned SET search_path TO provsql_test,provsql; -- foldSemiringIdentities (gated by provsql.simplify_on_load) drops -- identity wires from gate_plus / gate_times and collapses the -- empty-sum / empty-product to the corresponding identity gate. -- We assert the simplified shape via simplified_circuit_subgraph, -- which dispatches through the in-memory loader so the fold result is -- visible. SET provsql.simplify_on_load = on; -- Helper: count the unique nodes and root gate_type of the simplified -- subgraph rooted at @p g. A successful empty-sum / empty-product -- collapse leaves a single-node circuit with the identity gate type. CREATE TEMP TABLE sim_q (label text, root_kind text, n_nodes int); -- (1) plus(zero, zero) collapses to gate_zero. Empty sum is the -- additive identity. DO $$ DECLARE g uuid := public.uuid_generate_v4(); rows jsonb; BEGIN PERFORM provsql.create_gate(g, 'plus', ARRAY[provsql.gate_zero(), provsql.gate_zero()]); rows := provsql.simplified_circuit_subgraph(g, 5); INSERT INTO sim_q VALUES ('plus_of_two_zeros', rows -> 0 ->> 'gate_type', (SELECT COUNT(DISTINCT e->>'node') FROM jsonb_array_elements(rows) e)::int); END $$; -- (2) times(one, one) collapses to gate_one. Empty product is the -- multiplicative identity. DO $$ DECLARE g uuid := public.uuid_generate_v4(); rows jsonb; BEGIN PERFORM provsql.create_gate(g, 'times', ARRAY[provsql.gate_one(), provsql.gate_one()]); rows := provsql.simplified_circuit_subgraph(g, 5); INSERT INTO sim_q VALUES ('times_of_two_ones', rows -> 0 ->> 'gate_type', (SELECT COUNT(DISTINCT e->>'node') FROM jsonb_array_elements(rows) e)::int); END $$; -- (3) Nested plus(plus(zero,zero), plus(zero,zero)) cascades to -- gate_zero through the fixpoint loop in Phase 1: inner pluses -- collapse to gate_zero, then the outer plus's wires all become -- identity and it collapses too. DO $$ DECLARE g uuid := public.uuid_generate_v4(); i1 uuid := public.uuid_generate_v4(); i2 uuid := public.uuid_generate_v4(); rows jsonb; BEGIN PERFORM provsql.create_gate(i1, 'plus', ARRAY[provsql.gate_zero(), provsql.gate_zero()]); PERFORM provsql.create_gate(i2, 'plus', ARRAY[provsql.gate_zero(), provsql.gate_zero()]); PERFORM provsql.create_gate(g, 'plus', ARRAY[i1, i2]); rows := provsql.simplified_circuit_subgraph(g, 5); INSERT INTO sim_q VALUES ('plus_of_two_empty_pluses', rows -> 0 ->> 'gate_type', (SELECT COUNT(DISTINCT e->>'node') FROM jsonb_array_elements(rows) e)::int); END $$; -- (4) times whose first wire is an empty-product times and second -- wire is an empty-sum plus. Phase 1 collapses the inner gates; -- Phase 2's gate_times absorber then resolves the outer times to -- gate_zero (multiplicative zero is the universal absorber). DO $$ DECLARE g uuid := public.uuid_generate_v4(); i_one uuid := public.uuid_generate_v4(); i_zero uuid := public.uuid_generate_v4(); rows jsonb; BEGIN PERFORM provsql.create_gate(i_one, 'times', ARRAY[provsql.gate_one(), provsql.gate_one()]); PERFORM provsql.create_gate(i_zero, 'plus', ARRAY[provsql.gate_zero(), provsql.gate_zero()]); PERFORM provsql.create_gate(g, 'times', ARRAY[i_one, i_zero]); rows := provsql.simplified_circuit_subgraph(g, 5); INSERT INTO sim_q VALUES ('times_of_empty_product_and_empty_sum', rows -> 0 ->> 'gate_type', (SELECT COUNT(DISTINCT e->>'node') FROM jsonb_array_elements(rows) e)::int); END $$; -- (5) plus over two times-with-zero-wire children. Phase 2's -- gate_times absorber mutates each inner times to gate_zero, which -- then becomes a fresh empty-sum opportunity for the outer plus on a -- subsequent iteration of the fixpoint loop. Models the RangeCheck- -- driven shape where every UNION branch's gate_cmp is decided false -- (e.g. WHERE pm25>35 on uniforms with support [10,22] and [15,28]). DO $$ DECLARE g uuid := public.uuid_generate_v4(); i1 uuid := public.uuid_generate_v4(); i2 uuid := public.uuid_generate_v4(); in1 uuid := public.uuid_generate_v4(); in2 uuid := public.uuid_generate_v4(); rows jsonb; BEGIN PERFORM provsql.create_gate(in1, 'input'); PERFORM provsql.create_gate(in2, 'input'); PERFORM provsql.create_gate(i1, 'times', ARRAY[in1, provsql.gate_zero()]); PERFORM provsql.create_gate(i2, 'times', ARRAY[in2, provsql.gate_zero()]); PERFORM provsql.create_gate(g, 'plus', ARRAY[i1, i2]); rows := provsql.simplified_circuit_subgraph(g, 5); INSERT INTO sim_q VALUES ('plus_of_two_zero_absorbed_times', rows -> 0 ->> 'gate_type', (SELECT COUNT(DISTINCT e->>'node') FROM jsonb_array_elements(rows) e)::int); END $$; SELECT label, root_kind, n_nodes FROM sim_q ORDER BY label; DROP TABLE sim_q;