Host-append decomposition for RoseTree-level multi-tree insertion #
The RoseTree-level substrate for Nonplanar.insertionMultiset_add_host:
multi-graft into a concatenated host list host_A ++ host_B
decomposes as a sum over boolean assignments of guests to either
host_A or host_B, with each side recursively multi-grafted
independently.
Architecture #
The substrate is kBucketSum (§0): a polymorphic k-way bucketed
enumeration that assigns each guest to one of idx buckets, then
applies a leaf function to the final assignment. Its key identity
kBucketSum_assignment_rewrite collapses the per-guest recursion into a
single bind over all bucket assignments.
hostBucketSum (§1) is the 2-bucket (Bool-indexed) instance splitting
guests between two arbitrary host forests, with a parallel
cartesian-product leaf; hostBucketSum_assignment_rewrite is derived
from the general identity via hostBucketSum_eq_kBucketSum. The bridge
hostBucketSum_eq_insertionForest is proved by induction on host_A.
This is the RoseTree-level companion to the Nonplanar.insertionMultiset_add_host
combinatorial identity used in GrossmanLarsonAssoc.lean's
Oudom-Guin Prop 2.7.iii proof.
Status #
[UPSTREAM] candidate. Sorry-free.
§0: kBucketSum — k-way bucketed enumeration substrate #
Polymorphic substrate generalising the bucket-aggregator patterns used
in RoseTree-level multi-graft proofs (Foissy 2021, Marcolli-Chomsky-Berwick
2025, Oudom-Guin 2004). For each item in remaining, a choice from
idx selects a bucket; items accumulate into the per-bucket lists
pres. At empty remaining, the leaf function consumes the final
assignment. hostBucketSum (§1, 2 buckets) and hostTripleSum (§3,
3 buckets) are instances.
The slice of items from Ts whose assignment in assn equals t.
Equations
- RoseTree.Pathed.bucketSlice Ts assn t = List.filterMap (fun (p : ι × τ) => if p.2 = t then some p.1 else none) (Ts.zip assn)
Instances For
The Bool-true bucket slice keeps the items whose bit is set.
The Bool-false bucket slice keeps the items whose bit is unset.
k-way bucketed enumeration. For each item in remaining, bind over
idx to choose a bucket; the accumulator pres t for that bucket
grows by one item. At empty remaining, apply leaf.
Equations
- RoseTree.Pathed.kBucketSum idx leaf pres [] = leaf pres
- RoseTree.Pathed.kBucketSum idx leaf pres (x_1 :: rest) = (↑idx).bind fun (t : τ) => RoseTree.Pathed.kBucketSum idx leaf (Function.update pres t (pres t ++ [x_1])) rest
Instances For
Key identity: kBucketSum over remaining items Ts equals a
single bind over all length-Ts.length assignments (drawn from
idx) of the leaf applied to the accumulators augmented by the
per-bucket slice of Ts.
§1: hostBucketSum aggregator #
Splits a list of guest trees into two buckets — those destined for
host_A and those destined for host_B — by accumulating boolean
choices for each remaining guest. At the leaf, the cartesian product of
each side's insertionForest is concatenated.
Two-host aggregator: at the leaf (no remaining guests), produce
the cartesian product of insertionForest host_A pre_A and
insertionForest host_B pre_B, joined by list concatenation.
At a cons, bind over [true, false] and extend either bucket.
Equations
- One or more equations did not get rendered due to their size.
Instances For
hostBucketSum as a kBucketSum instance: 2 buckets indexed by Bool,
parallel cartesian-product leaf.
Assignment rewrite: hostBucketSum accumulating into pre_A/pre_B
over remaining guests Ts equals the sum over [true, false]-
assignments of Ts of hostBucketSum on empty remaining with the
accumulators augmented by the partition. Specialises the general
kBucketSum_assignment_rewrite to the 2-bucket Bool instance.
§2: Base case — hostBucketSum [] host_B [] [] guests = insertionForest host_B guests #
When host_A = [], only the "all-false" boolean assignment can
produce a non-zero insertionForest [] _ ≠ 0, since
insertionForest [] _ = 0 whenever the second argument is non-empty.
The all-false path gives ({[]} ×ˢ insertionForest host_B guests).map (++),
which collapses to insertionForest host_B guests.
§3: 3-bucket aggregator and the full bridge #
The headline RoseTree-level identity. Combined with the Nonplanar lift below
(via Quotient.out + host-Perm invariance lifted through Nonplanar.mk),
this yields the substrate for Nonplanar.insertionMultiset_add_host.
The proof goes by induction on host_A. The base case (host_A = [])
is hostBucketSum_nil_A (above). The inductive case host_A = T :: F_A
proceeds via a 3-bucket aggregator hostTripleSum that explicitly
partitions guests into three buckets {T-bucket, F_A-bucket, host_B-bucket}.
We then prove:
hostBucketSum_eq_hostTripleSum: LHS (the 2-stephostBucketSum) equals the 3-bucket sum (reorganizing "A-vs-B then T-vs-F_A within A").insertionForest_cons_append_eq_hostTripleSum: RHS (theinsertionForestoverT :: (F_A ++ host_B)) equals the 3-bucket sum (using the outer IH onF_Ato convertinsertionForest (F_A ++ host_B) YintohostBucketSum F_A host_B, reorganizing "T-vs-rest then F_A-vs-host_B within rest").
Uniform decomposition of insertionForest (T :: F) X over [true, false]-assignments
of X's elements to the T-bucket or F-bucket. Works for empty X via singleton bind.
Length lemma: every element of listChoices xs n has length exactly n.
Used in the cons case of hostBucketSum_eq_hostTripleSum_aux to invoke
List.zip_append.
§4: Connecting hostTripleSum with insertion T ∘ hostBucketSum F_A host_B #
Lemma A reduces hostBucketSum (T :: F_A) host_B [] [] guests to
hostTripleSum T F_A host_B [] [] [] guests. To complete the bridge, we
need hostTripleSum T F_A host_B [] [] [] guests = insertionForest (T :: (F_A ++ host_B)) guests.
Approach: generalize to hostTripleSum_T_split:
hostTripleSum T F_A host_B pre_T pre_FA pre_B remaining =
bind α over remaining.length:
(insertion T (pre_T ++ filter_true remaining α)).bind T' =>
(hostBucketSum F_A host_B pre_FA pre_B (filter_false remaining α)).map (T' :: ·)
Then for pre_T = pre_FA = pre_B = [], combine with the IH hostBucketSum F_A host_B = insertionForest (F_A ++ host_B) to close the bridge.
Requires listChoices_succ_cons_bind (the cons-prepending analog of
listChoices_succ_append_bind).
§5: Host-Perm invariance at the multiset-of-multiset level #
insertionForest is invariant under permutation of host trees, but only at
the level where output lists are wrapped via Multiset.ofList ∘ List.map mk
(i.e., the level used by Nonplanar.insertionMultiset). The list structure
of inner outputs (which is host-position-correlated) is discarded by this
outer wrapper, allowing host trees to be permuted without changing the
multiset-of-multiset image.
The key combinatorial lemma is the swap symmetry of two adjacent host trees,
which we prove via hostTripleSum's 3-bucket structure: when the F_A bucket
is a singleton [T₂], swapping the T-bucket with the F_A-bucket gives a
configuration symmetric in (T₁, T₂) at the multiset level.
Host-Perm invariance at the multiset-of-multiset level: when host
trees are permuted, the (insertionForest host gs).map (Multiset.ofList ∘ List.map mk)
is unchanged.
This is the key invariance used by Nonplanar.insertionMultiset_add_host
(and similar Nonplanar-side lifts) to bridge (A + B).toList.map Q.out
with A.toList.map Q.out ++ B.toList.map Q.out.
§6: Bit-vector ↔ powerset bridge #
For a list l : List β, bit-vectors of length |l| enumerate sublists
of l (the elements where the bit is true). At the multiset level, the
collection of (filter_t, filter_f) pairs over all bit-vectors equals
the collection of (s, ↑l - s) over s ∈ (↑l).powerset. Used by
Nonplanar.insertionMultiset_add_host to bridge the
hostBucketSum_assignment_rewrite form (bind over bit-vectors) with
the C.powerset.bind form on the RHS.
Length lemma: every element of listChoices [b₁, b₂] n has length exactly n.
A re-export of the existing mem_listChoices_length for [true, false].
Bit-vector ↔ powerset bridge (paired form): enumerating bit-vectors
and pairing (filter_t, filter_f) gives the powerset paired with
complement (s, ↑l - s). Derived from the single-component version +
filterMap_f_eq_sub.
§7: Guest-multiset invariance at the msform level #
(insertionForest host gs).map msform depends only on the multiset image
of gs.map mk, not on the RoseTree representatives or order. This combines
guest-Perm invariance + guest-PermEquiv invariance into a single lemma
matching the level used by Nonplanar.insertionMultiset.
Combined guest invariance at the multiset-of-multiset level.