@@ -254,6 +254,75 @@ theorem card_productQuotientRules {Z₁ Z₂ A : Type}
254254 Fintype.card A ^ (Fintype.card Z₁ * Fintype.card Z₂) := by
255255 rw [Fintype.card_fun, Fintype.card_prod]
256256
257+ /--
258+ The reachable image of a product map is contained in the product of the two
259+ reachable component images.
260+ -/
261+ theorem productMap_image_subset_product_images
262+ {Ω₁ Ω₂ Z₁ Z₂ : Type }
263+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂]
264+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
265+ QuotientImageFinset (productMap Q₁ Q₂) ⊆
266+ (QuotientImageFinset Q₁).product (QuotientImageFinset Q₂) := by
267+ intro z hz
268+ rcases Finset.mem_image.mp hz with ⟨p, _hp, hp⟩
269+ rw [← hp]
270+ exact Finset.mem_product.mpr
271+ ⟨Finset.mem_image.mpr ⟨p.1 , Finset.mem_univ p.1 , rfl⟩,
272+ Finset.mem_image.mpr ⟨p.2 , Finset.mem_univ p.2 , rfl⟩⟩
273+
274+ /--
275+ The number of reachable product codes is bounded by the product of the numbers
276+ of reachable component codes.
277+ -/
278+ theorem productMap_image_card_le_product_images_card
279+ {Ω₁ Ω₂ Z₁ Z₂ : Type }
280+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂]
281+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
282+ (QuotientImageFinset (productMap Q₁ Q₂)).card ≤
283+ (QuotientImageFinset Q₁).card * (QuotientImageFinset Q₂).card := by
284+ calc
285+ (QuotientImageFinset (productMap Q₁ Q₂)).card
286+ ≤ ((QuotientImageFinset Q₁).product (QuotientImageFinset Q₂)).card :=
287+ Finset.card_le_card (productMap_image_subset_product_images Q₁ Q₂)
288+ _ = (QuotientImageFinset Q₁).card * (QuotientImageFinset Q₂).card := by
289+ simp
290+
291+ /--
292+ Rules on the reachable product image have search-space size
293+ `|A| ^ |image(productMap Q₁ Q₂)|`.
294+ -/
295+ theorem card_productImageQuotientRules
296+ {Ω₁ Ω₂ Z₁ Z₂ A : Type }
297+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂] [Fintype A]
298+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
299+ Fintype.card (QuotientImageBucket (productMap Q₁ Q₂) → A) =
300+ Fintype.card A ^ (QuotientImageFinset (productMap Q₁ Q₂)).card := by
301+ classical
302+ letI : Fintype (QuotientImageBucket (productMap Q₁ Q₂)) :=
303+ Fintype.ofFinset (QuotientImageFinset (productMap Q₁ Q₂)) (by
304+ intro z
305+ constructor <;> intro hz <;> exact hz)
306+ rw [Fintype.card_fun]
307+ congr
308+ simp [QuotientImageBucket]
309+
310+ /--
311+ Product-image quotient rules are bounded by assigning labels to every
312+ component-image pair.
313+ -/
314+ theorem card_productImageQuotientRules_le_product_images
315+ {Ω₁ Ω₂ Z₁ Z₂ A : Type }
316+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂] [Fintype A]
317+ [Nonempty A]
318+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
319+ Fintype.card (QuotientImageBucket (productMap Q₁ Q₂) → A) ≤
320+ Fintype.card A ^
321+ ((QuotientImageFinset Q₁).card * (QuotientImageFinset Q₂).card) := by
322+ rw [card_productImageQuotientRules Q₁ Q₂]
323+ exact Nat.pow_le_pow_right (Fintype.card_pos)
324+ (productMap_image_card_le_product_images_card Q₁ Q₂)
325+
257326namespace RuleFactorsThrough
258327
259328/-- Pairing two product-factorized targets is equivalent to factoring both components. -/
@@ -301,6 +370,26 @@ structure ComparisonObs (Ω₁ Ω₂ : Type) where
301370 second : Ω₂
302371deriving DecidableEq
303372
373+ /-- Finite comparison observations are equivalent to left/right/right triples. -/
374+ def comparisonObsEquivProd (Ω₁ Ω₂ : Type ) :
375+ ComparisonObs Ω₁ Ω₂ ≃ Ω₁ × Ω₂ × Ω₂ where
376+ toFun c := (c.left, c.first, c.second)
377+ invFun x := {
378+ left := x.1
379+ first := x.2 .1
380+ second := x.2 .2
381+ }
382+ left_inv c := by
383+ cases c
384+ rfl
385+ right_inv x := by
386+ cases x
387+ rfl
388+
389+ noncomputable instance comparisonObsFintype {Ω₁ Ω₂ : Type }
390+ [Fintype Ω₁] [Fintype Ω₂] : Fintype (ComparisonObs Ω₁ Ω₂) :=
391+ Fintype.ofEquiv (Ω₁ × Ω₂ × Ω₂) (comparisonObsEquivProd Ω₁ Ω₂).symm
392+
304393/-- Product quotient for a left item and two right items. -/
305394def comparisonMap {Ω₁ Ω₂ Z₁ Z₂ : Type }
306395 (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
@@ -396,4 +485,102 @@ theorem rankByScore_factorsThrough_of_score_factorsThrough
396485 cases c
397486 simp [rankByScore, comparisonMap, hscoreQ]
398487
488+ /-! ## Comparison image bounds -/
489+
490+ /--
491+ The ambient box of reachable comparison codes induced by one left image and two
492+ right images.
493+ -/
494+ def ComparisonImageBox {Ω₁ Ω₂ Z₁ Z₂ : Type }
495+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂]
496+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) : Finset (ComparisonObs Z₁ Z₂) :=
497+ ((QuotientImageFinset Q₁).product
498+ ((QuotientImageFinset Q₂).product (QuotientImageFinset Q₂))).image
499+ (fun z => {
500+ left := z.1
501+ first := z.2 .1
502+ second := z.2 .2
503+ })
504+
505+ /--
506+ The reachable image of a comparison map is contained in the box of reachable
507+ left/right/right component codes.
508+ -/
509+ theorem comparisonMap_image_subset_imageBox
510+ {Ω₁ Ω₂ Z₁ Z₂ : Type }
511+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂]
512+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
513+ QuotientImageFinset (comparisonMap Q₁ Q₂) ⊆
514+ ComparisonImageBox Q₁ Q₂ := by
515+ intro z hz
516+ rcases Finset.mem_image.mp hz with ⟨c, _hc, hc⟩
517+ rw [← hc]
518+ unfold ComparisonImageBox
519+ apply Finset.mem_image.mpr
520+ refine ⟨(Q₁ c.left, (Q₂ c.first, Q₂ c.second)), ?_, rfl⟩
521+ exact Finset.mem_product.mpr
522+ ⟨Finset.mem_image.mpr ⟨c.left, Finset.mem_univ c.left, rfl⟩,
523+ Finset.mem_product.mpr
524+ ⟨Finset.mem_image.mpr ⟨c.first, Finset.mem_univ c.first, rfl⟩,
525+ Finset.mem_image.mpr ⟨c.second, Finset.mem_univ c.second, rfl⟩⟩⟩
526+
527+ /--
528+ The number of reachable comparison codes is bounded by
529+ `|image Q₁| * |image Q₂| * |image Q₂|`.
530+ -/
531+ theorem comparisonMap_image_card_le_product_images_card
532+ {Ω₁ Ω₂ Z₁ Z₂ : Type }
533+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂]
534+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
535+ (QuotientImageFinset (comparisonMap Q₁ Q₂)).card ≤
536+ (QuotientImageFinset Q₁).card *
537+ (QuotientImageFinset Q₂).card * (QuotientImageFinset Q₂).card := by
538+ calc
539+ (QuotientImageFinset (comparisonMap Q₁ Q₂)).card
540+ ≤ (ComparisonImageBox Q₁ Q₂).card :=
541+ Finset.card_le_card (comparisonMap_image_subset_imageBox Q₁ Q₂)
542+ _ ≤ ((QuotientImageFinset Q₁).product
543+ ((QuotientImageFinset Q₂).product (QuotientImageFinset Q₂))).card := by
544+ unfold ComparisonImageBox
545+ exact Finset.card_image_le
546+ _ = (QuotientImageFinset Q₁).card *
547+ (QuotientImageFinset Q₂).card * (QuotientImageFinset Q₂).card := by
548+ simp [mul_assoc]
549+
550+ /--
551+ Rules on the reachable comparison image have search-space size
552+ `|A| ^ |image(comparisonMap Q₁ Q₂)|`.
553+ -/
554+ theorem card_comparisonImageQuotientRules
555+ {Ω₁ Ω₂ Z₁ Z₂ A : Type }
556+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂] [Fintype A]
557+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
558+ Fintype.card (QuotientImageBucket (comparisonMap Q₁ Q₂) → A) =
559+ Fintype.card A ^ (QuotientImageFinset (comparisonMap Q₁ Q₂)).card := by
560+ classical
561+ letI : Fintype (QuotientImageBucket (comparisonMap Q₁ Q₂)) :=
562+ Fintype.ofFinset (QuotientImageFinset (comparisonMap Q₁ Q₂)) (by
563+ intro z
564+ constructor <;> intro hz <;> exact hz)
565+ rw [Fintype.card_fun]
566+ congr
567+ simp [QuotientImageBucket]
568+
569+ /--
570+ Comparison-image quotient rules are bounded by assigning labels to every
571+ left/right/right component-image triple.
572+ -/
573+ theorem card_comparisonImageQuotientRules_le_product_images
574+ {Ω₁ Ω₂ Z₁ Z₂ A : Type }
575+ [Fintype Ω₁] [Fintype Ω₂] [DecidableEq Z₁] [DecidableEq Z₂] [Fintype A]
576+ [Nonempty A]
577+ (Q₁ : Ω₁ → Z₁) (Q₂ : Ω₂ → Z₂) :
578+ Fintype.card (QuotientImageBucket (comparisonMap Q₁ Q₂) → A) ≤
579+ Fintype.card A ^
580+ ((QuotientImageFinset Q₁).card *
581+ (QuotientImageFinset Q₂).card * (QuotientImageFinset Q₂).card) := by
582+ rw [card_comparisonImageQuotientRules Q₁ Q₂]
583+ exact Nat.pow_le_pow_right (Fintype.card_pos)
584+ (comparisonMap_image_card_le_product_images_card Q₁ Q₂)
585+
399586end OrdvecFormalization
0 commit comments