@@ -289,6 +289,47 @@ rewrite fcards0 RField.expr0 RField.mulr1 => <-.
289289apply: mu_eq_support => xs; rewrite supp_dlist //= => -[? ?]; smt(in_fset0).
290290qed.
291291
292+ lemma dmap_dlist_partial_perm [' a] (x0 : ' a) (d : ' a distr) (f : int -> int ) (n k : int ) :
293+ 0 <= k
294+ => 0 <= n
295+ => is_lossless d
296+ => (forall i j, 0 <= i < k => 0 <= j < k => f i = f j => i = j)
297+ => (forall i, 0 <= i < k => 0 <= f i < n)
298+ => dmap (dlist d n) (fun xs => mkseq (fun i => nth x0 xs (f i)) k)
299+ = dlist d k.
300+ proof.
301+ move=> ge0_k ge0_n lld injf inrgf.
302+ elim: k ge0_k n ge0_n f injf inrgf.
303+ - move=> n ge0_n f injf inrgf; rewrite [dlist d 0 ]dlist0 // .
304+ rewrite -(eq_dmap _ (fun _ => [])) // =.
305+ - by move=> ? /=; rewrite mkseq0.
306+ by rewrite dmap_cst // ; apply/dlist_ll/lld.
307+ move=> k ge0_k ih n ge0_n f injf inrgf.
308+ pose k1 := f k; pose k2 := n - (k1 + 1 ).
309+ have ->: n = (k1 + 1 ) + k2 by rewrite /k1 /k2 #ring.
310+ rewrite dlist_djoin 1 :/# -cat_nseq ~-1 :/# nseqSr 1 :/#.
311+ rewrite -cats1 -catA /= djoin_perm_s1s /= dmap_dlet /=.
312+ rewrite -!dlist_djoin ~-1 :/# /=.
313+ pose c (i : int ) := f i - b2i (k1 <= f i).
314+ pose h (a : ' a list) := mkseq (fun i => nth x0 a (c i)) k.
315+ pose C (a : ' a list * ' a list) := a.`1 ++ a.`2.
316+ pose F (a : ' a list) (x : ' a) := rcons (h a) x.
317+ rewrite -(in_eq_dlet (fun (ds : ' a list * ' a list) => dmap d (F (C ds)))).
318+ - move=> ds /supp_dprod => /= []; rewrite !supp_dlist ~-1:/#.
319+ move=> [#] hsz1 _ hsz2 _; rewrite dmap_comp &(eq_dmap) /=.
320+ move=> x @/(\o ) /=; rewrite mkseqS 1:/# /F /=; congr; last first.
321+ - by rewrite nth_cat ifF 1:/# /= ifT 1:/#.
322+ apply: eq_in_mkseq => i rgi /=; rewrite !nth_cat.
323+ rewrite /c hsz1 lezNgt; case: (f i < k1) => /= [->//|?].
324+ by rewrite !ifF ~-1:/# addrAC.
325+ rewrite -(dlet_dmap _ C (fun ds => dmap d (F ds))) -dlist_add ~-1:/#.
326+ rewrite -(dmap_dprodE _ _ (fun (xy : _ * _) => F xy.`1 xy.`2)) /F /=.
327+ rewrite dlistSr ~-1:/# /= !dmap_dprodE_swap /= &(in_eq_dlet) /=.
328+ move=> x _; rewrite -(dmap_comp h (fun xs => rcons xs x)); congr.
329+ apply: ih => @/k2; 2,3: by smt().
330+ have ->: k1 + (n - (k1 + 1)) = n - 1 by ring.
331+ by have := inrgf 0 _; smt().
332+ qed.
292333
293334abstract theory Program.
294335 type t.
0 commit comments