diff options
| author | Enrico Tassi | 2018-04-17 16:57:13 +0200 |
|---|---|---|
| committer | Enrico Tassi | 2018-04-17 16:57:13 +0200 |
| commit | eaa90cf9520e43d0b05fc6431a479e6b9559ef0e (patch) | |
| tree | 8499953a468a8d8be510dd0d60232cbd8984c1ec /mathcomp/odd_order/PFsection3.v | |
| parent | c1ec9cd8e7e50f73159613c492aad4c6c40bc3aa (diff) | |
move odd_order to its own repository
Diffstat (limited to 'mathcomp/odd_order/PFsection3.v')
| -rw-r--r-- | mathcomp/odd_order/PFsection3.v | 1864 |
1 files changed, 0 insertions, 1864 deletions
diff --git a/mathcomp/odd_order/PFsection3.v b/mathcomp/odd_order/PFsection3.v deleted file mode 100644 index e229772..0000000 --- a/mathcomp/odd_order/PFsection3.v +++ /dev/null @@ -1,1864 +0,0 @@ -(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *) -(* Distributed under the terms of CeCILL-B. *) -Require Import mathcomp.ssreflect.ssreflect. -From mathcomp -Require Import ssrbool ssrfun eqtype ssrnat seq path div choice. -From mathcomp -Require Import fintype tuple finfun bigop prime ssralg matrix poly finset. -From mathcomp -Require Import fingroup morphism perm automorphism quotient action finalg zmodp. -From mathcomp -Require Import gfunctor center gproduct cyclic pgroup abelian frobenius. -From mathcomp -Require Import mxalgebra mxrepresentation vector falgebra fieldext galois. -From mathcomp -Require Import ssrnum rat algC algnum classfun character. -From mathcomp -Require Import integral_char inertia vcharacter. -From mathcomp -Require Import PFsection1 PFsection2. - -(******************************************************************************) -(* This file covers Peterfalvi, Section 3: TI-Subsets with Cyclic Normalizers *) -(******************************************************************************) -(* Given a direct product decomposition defW : W1 \x W2 = W, we define here: *) -(* cyclicTIset defW == the set complement of W1 and W2 in W; this *) -(* (locally) V definition is usually Let-bound to V. *) -(* := W :\: (W1 :|: W2). *) -(* cyclicTI_hypothesis G defW <-> W is a cyclic of odd order that is the *) -(* normaliser in G of its non-empty TI subset *) -(* V = cyclicTIset defW = W :\: (W1 :|: W2). *) -(* -> This is Peterfalvi, Hypothesis (3.1), or Feit-Thompson (13.1). *) -(* cyclicTIirr defW i j == the irreducible character of W coinciding with *) -(* (locally) w_ i j chi_i and 'chi_j on W1 and W2, respectively. *) -(* This notation is usually Let-bound to w_ i j. *) -(* := 'chi_(dprod_Iirr defW (i, j)). *) -(* cfCyclicTIset defW i j == the virtual character of 'Z[irr W, V] coinciding *) -(* (locally) alpha_ i j with 1 - chi_i and 1 - 'chi_j on W1 and W2, *) -(* respectively. This definition is denoted by *) -(* alpha_ i j in this file, and is only used in the *) -(* proof if Peterfalvi (13.9) in the sequel. *) -(* := cfDprod defW (1 - 'chi_i) (1 - 'chi_j). *) -(* = 1 - w_ i 0 - w_ 0 j + w_ i j. *) -(* cfCyclicTIsetBase defW := the tuple of all the alpha_ i j, for i, j != 0. *) -(* (locally) cfWVbase This is a basis of 'CF(W, V); this definition is *) -(* not used outside this file. *) -(* For ctiW : cyclicTI_hypothesis defW G we also define *) -(* cyclicTIiso ctiW == a linear isometry from 'CF(W) to 'CF(G) that *) -(* (locally) sigma that extends induction on 'CF(W, V), maps the *) -(* w_ i j to virtual characters, and w_ 0 0 to 1. *) -(* This definition is usually Let-bound to sigma, *) -(* and only depends extensionally on W, V and G. *) -(* (locally) eta_ i j := sigma (w_ i j), as in sections 13 and 14 of *) -(* tha Peterfalv text. *) -(* cyclicTI_NC ctiW phi == the number of eta_ i j constituents of phi. *) -(* (locally) NC phi := #|[set ij | '[phi, eta_ ij .1 ij.2] != 0]|. *) -(* The construction of sigma involves a large combinatorial proof, for which *) -(* it is worthwhile to use reflection techniques to automate mundane and *) -(* repetitive arguments. We isolate the necessary boilerplate in a separate *) -(* CyclicTIisoReflexion module. *) -(******************************************************************************) - -Set Implicit Arguments. -Unset Strict Implicit. -Unset Printing Implicit Defensive. - -Import GroupScope GRing.Theory Num.Theory. -Local Open Scope ring_scope. - -Section Definitions. - -Variables (gT : finGroupType) (G W W1 W2 : {set gT}). - -Definition cyclicTIset of W1 \x W2 = W := W :\: (W1 :|: W2). - -Definition cyclicTI_hypothesis (defW : W1 \x W2 = W) := - [/\ cyclic W, odd #|W| & normedTI (cyclicTIset defW) G W]. - -End Definitions. - -(* These is defined as a Notation which clients can bind with a Section Let *) -(* that can be folded easily. *) -Notation cyclicTIirr defW i j := 'chi_(dprod_Iirr defW (i, j)). - -Module CyclicTIisoReflexion. - -(******************************************************************************) -(* Support for carrying out the combinatorial parts of the proof of Theorem *) -(* (3.5) by reflection. Specifically, we need to show that in a rectangular *) -(* array of virtual characters of norm 3, of even dimensions, and such that *) -(* the dot product of two entries is 1 if they are on the same row or column, *) -(* the entries of each column contain a "pivot" normal virtual character *) -(* orthogonal to all other columns. The proof never needs to consider more *) -(* than a 4 x 2 rectangle, but frequently renumbers lines, columns and *) -(* orthonormal components in order to do so. *) -(* We want to use reflection to automate this renumbering; we also want to *) -(* automate the evaluation of the dot product constaints for partially *) -(* described entries of the matrix. *) -(* To do so we define a "theory" data structure to store a reifed form of *) -(* such partial descriptions: a set of "clauses", each consisting in an index *) -(* (i, j) into the array, and a collection of "literals" (k, v) representing *) -(* constraints '[b_(i, j), x`_k] = v%:~R, with v = 0, 1 or -1. A clause with *) -(* exactly three nonzero literals defines b_(i, j) exactly. *) -(* We define special notation for the concrete instances that appear in *) -(* reflected proofs; for example *) -(* |= & b11 = -x1 + x2 + x3 & x1, ~x2 in b12 & ? in b31 *) -(* denotes the "theory" of arrays whose two left entries decomposes into *) -(* x1 + x2 + x3 for some orthonormal x1, x2, and x3, such that the second top *) -(* entry has x1 is a signed component but is orthogonal to x2, and which have *) -(* an (unconstrained) first entry in the third column. (The concrete encoding *) -(* shifts indices to start at 0.) *) -(* The "models" in which such theories are interpreted supply the dimensions *) -(* of the array, which must be even, nonequal and at least 2, the function *) -(* mapping indices to array entries, which must be virtual characters with *) -(* the requisite norms and dot products, and an orthonormal sequence of *) -(* virtual characters that will be used to interpret the xij; a model coerces *) -(* to any of these three components. *) -(* We are primarily interested in two predicates: *) -(* sat m th <=> the interpretation of th in m is well-defined (no out of *) -(* bound indices) and valid (all constraints true). *) -(* unsat th <-> forall m, ~ sat m th *) -(* While the main theorem of this section, column_pivot, can be seen as an *) -(* instance of "sat", all the principal combinatorial lemmas use "unsat", *) -(* whose universal quantifier allows symmetry reductions. We present the set *) -(* of lemmas implementing reflection-assisted proofs of "unsat th" as a small *) -(* domain-specific proof language consisting of the following tactics: *) -(* consider bij ::= add a clause for bij, which must not appear in th, *) -(* changing the goal to unsat th & ? in bij. *) -(* bij must be within a 4 x 2 bounding box, and th *) -(* must be symmetric if bij "breaks" the 2 x 2 box. *) -(* fill bij ::= add an x(k.+1) literal to the bij clause in th, *) -(* where x1, ..., xk are all the normal characters *) -(* appearing in th, and the clause for bij exists and *) -(* contains assumptions for all of x1, ..., xk, at *) -(* two of which are nonzero. *) -(* uwlog Dcl: cl [by tac] ::= add the clause cl to th, replacing an existing *) -(* clause for the same matrix entry. This produces a *) -(* side goal of unsat th, but with an additional *) -(* assumption Dcl : unsat th+cl, which can be resolved *) -(* with the optional "by tac". *) -(* uhave lit in bij as T(ij, kl) ::= adds the literal lit (one of xk, -xk, or *) -(* ~xk) to an existing clause for bij in th, using the *) -(* reflection lemma T(ij, kl) to rule out the other *) -(* possibilities for xk. Here T can be either O *) -(* (general dot product evaluation) or L (specific *) -(* line/column constraints following from (3.5.2)). *) -(* uhave lit, lit' in bij as T(ij, kl) ::= adds both lit and lit'. *) -(* uhave lit | lit' in bij as T(ij, kl) ::= produces two subgoals, where lit *) -(* (resp. lit') is added to the ... in bij clause in *) -(* th, using T(ij, kl) to eliminate the third literal. *) -(* (lit and lit' must constrain the same component). *) -(* uhave lit | lit' | lit'' in bij ::= produces three subgoals, where lit *) -(* (resp. lit', lit'') is added to the bij clause in *) -(* th; lit, lit', lit'' should be a permutation of xk, *) -(* -xk, and ~xk for some k. *) -(* uwlog Ebij: lit | lit' in bij as T(ij, kl) ::= adds lit to the bij clause *) -(* in th, but produces a side goal where lit' has been *) -(* added instead, with an additional assumption *) -(* Ebij: th + (lit in bij); T(ij, kl) is used to rule *) -(* out the third value. *) -(* counter to T(ij, kl) ::= use T(ij, kl) to conclude that unsat th. *) -(* uexact Hth' ::= use Hth' : unsat th', where th' is a subset of th *) -(* (with the same order of literals) to conclude. *) -(* symmetric to Hth' ::= use Hth' : unsat th', where th' is a permutation *) -(* of a subset of th (preserving columns, and with at *) -(* most one row exchange) to conclude. *) -(******************************************************************************) - -Import ssrint. - -(* Clause left-hand side, a reference to a value of beta; in the reference *) -(* model m, (i, j) stands for beta_ (inord i.+1) (inord j.+1). *) -Definition ref := (nat * nat)%type. -Implicit Type ij : ref. -Definition Ref b_ij : ref := edivn (b_ij - 11) 10. (* Ref 21 = (1, 0). *) -Notation "''b' ij" := (Ref ij) (at level 0, ij at level 0, format "''b' ij"). -Notation b11 := 'b11. Notation b12 := 'b12. -Notation b21 := 'b21. Notation b22 := 'b22. -Notation b31 := 'b31. Notation b32 := 'b32. -Notation b41 := 'b41. Notation b42 := 'b42. - -Definition bbox := (nat * nat)%type. (* bounding box for refs. *) -Implicit Type bb : bbox. -Identity Coercion pair_of_bbox : bbox >-> prod. - -Definition sub_bbox bb1 bb2 := (bb1.1 <= bb2.1)%N && (bb1.2 <= bb2.2)%N. -Definition wf_ref bb := [pred ij : ref | (ij.1 < bb.1)%N && (ij.2 < bb.2)%N]. -Definition dot_ref ij1 ij2 := ((ij1.1 == ij2.1).+1 * (ij1.2 == ij2.2).+1 - 1)%N. - -Lemma bbox_refl bb : sub_bbox bb bb. Proof. exact/andP. Qed. - -(* Clause right-hand side litteral, denoting the projection of the left-hand *) -(* side on an irreducible character of G: in a valid model m, (k, v) stands *) -(* for the component m`_k *~ v = (model_xi m)`_k, and for the projection *) -(* constraint '[m i j, m`_k] == v%:~R. *) -Definition lit := (nat * int)%type. (* +x1 = (0,1) ~x2 = (1,0) -x3 = (2, -1) *) -Implicit Types (kv : lit) (kvs : seq lit). -Definition Lit k1 v : lit := if (0 + k1)%N is k.+1 then (k, v) else (k1, v). -Notation "+x k" := (Lit k 1) (at level 0, k at level 0, format "+x k"). -Notation "-x k" := (Lit k (-1)) (at level 0, k at level 0, format "-x k"). -Notation "~x k" := (Lit k 0) (at level 0, k at level 0, format "~x k"). -Notation x1 := +x1. Notation x2 := +x2. -Notation x3 := +x3. Notation x4 := +x4. -Notation x5 := +x5. Notation x6 := +x6. -Notation x7 := +x7. Notation x8 := +x8. - -Definition AndLit kvs kv := kv :: kvs. -Definition AddLit := AndLit. -Notation "(*dummy*)" := (Prop Prop) (at level 0) : defclause_scope. -Arguments AddLit _%defclause_scope _. -Infix "+" := AddLit : defclause_scope. -Definition SubLit kvs kv := AddLit kvs (kv.1, - kv.2). -Arguments SubLit _%defclause_scope _. -Infix "-" := SubLit : defclause_scope. -Coercion LastLit kv := [:: kv]. - -Fixpoint norm_cl kvs : nat := - (if kvs is (_, v) :: kvs1 then `|v| ^ 2 + norm_cl kvs1 else 0)%N. - -Definition clause := (ref * seq lit)%type. -Implicit Type cl : clause. -Definition Clause ij kvs : clause := (ij, kvs). -Notation "& kv1 , .. , kvn 'in' ij" := - (Clause ij (AndLit .. (AndLit nil kv1) .. kvn)) - (at level 200, ij, kv1, kvn at level 0, - format "& kv1 , .. , kvn 'in' ij"). -Notation "& ? 'in' ij" := (Clause ij nil) - (at level 200, ij at level 0, format "& ? 'in' ij"). -Definition DefClause := Clause. -Arguments DefClause _ _%defclause_scope. -Notation "& ij = kvs" := (DefClause ij kvs) - (at level 200, ij at level 0, format "& ij = kvs"). - -Definition theory := seq clause. -Implicit Type th : theory. -Definition AddClause th cl : theory := cl :: th. -Notation "|= cl1 .. cln" := (AddClause .. (AddClause nil cl1) .. cln) - (at level 8, cl1, cln at level 200, - format "|= '[hv' cl1 '/' .. '/' cln ']'"). - -(* Transpose (W1 / W2 symmetry). *) - -Definition tr (ij : nat * nat) : ref := (ij.2, ij.1). -Definition tr_th th : theory := [seq (tr cl.1, cl.2) | cl <- th]. - -Lemma trK : involutive tr. Proof. by case. Qed. -Lemma tr_thK : involutive tr_th. Proof. by apply: mapK => [[[i j] kvs]]. Qed. - -(* Index range of a theory. *) - -Fixpoint th_bbox th : bbox := - if th is (i, j, _) :: th1 then - let: (ri, rj) := th_bbox th1 in (maxn i.+1 ri, maxn j.+1 rj) - else (0, 0)%N. - -Lemma th_bboxP th bb : - reflect {in th, forall cl, cl.1 \in wf_ref bb} (sub_bbox (th_bbox th) bb). -Proof. -pose in_bb := [pred cl : clause | cl.1 \in wf_ref bb]. -suffices ->: sub_bbox (th_bbox th) bb = all in_bb th by apply: allP. -elim: th => [|[[i j] _] th] //=; case: (th_bbox th) => ri rj /=. -by rewrite /sub_bbox /= !geq_max andbACA => ->. -Qed. -Arguments th_bboxP [th bb]. - -Fixpoint th_dim th : nat := - if th is (_, kvs) :: th1 then - foldr (fun kv => maxn kv.1.+1) (th_dim th1) kvs - else 0%N. - -Lemma th_dimP th bk : - reflect {in th, forall cl, {in cl.2, forall kv, kv.1 < bk}}%N - (th_dim th <= bk)%N. -Proof. -pose in_bk := [pred cl : clause | all (fun kv => kv.1 < bk)%N cl.2]. -suffices ->: (th_dim th <= bk)%N = all in_bk th. - by apply: (iffP allP) => bk_th cl /bk_th/allP. -elim: th => // [[_ kvs] th /= <-]; elim: kvs => //= kv kvs. -by rewrite -andbA geq_max => ->. -Qed. -Arguments th_dimP [th bk]. - -(* Theory and clause lookup. *) - -CoInductive get_spec T (P : T -> Prop) (Q : Prop) : option T -> Prop := - | GetSome x of P x : get_spec P Q (Some x) - | GetNone of Q : get_spec P Q None. - -Fixpoint get_cl ij (th : theory) : option clause := - if th is cl :: th1 then if cl.1 == ij then Some cl else get_cl ij th1 - else None. - -Lemma get_clP ij (th : theory) : - get_spec (fun cl : clause => cl \in th /\ cl.1 = ij) True (get_cl ij th). -Proof. -elim: th => /= [|cl th IHth]; first by right. -case: eqP => [Dij | _]; first by left; rewrite ?mem_head. -by case: IHth => [cl1 [th_cl1 Dij]|]; constructor; rewrite // mem_behead. -Qed. - -Fixpoint get_lit (k0 : nat) kvs : option int := - if kvs is (k, v) :: kvs1 then if k == k0 then Some v else get_lit k0 kvs1 - else None. - -Lemma get_litP k0 kvs : - get_spec (fun v => (k0, v) \in kvs) (k0 \notin unzip1 kvs) (get_lit k0 kvs). -Proof. -elim: kvs => [|[k v] kvs IHkvs /=]; [by right | rewrite inE eq_sym]. -have [-> | k'0] := altP eqP; first by left; rewrite ?mem_head. -by have [v0 kvs_k0v | kvs'k0] := IHkvs; constructor; rewrite // mem_behead. -Qed. - -(* Theory extension. *) - -Fixpoint set_cl cl2 th : wrapped theory := - if th is cl :: th1 then - let: Wrap th2 := set_cl cl2 th1 in - if cl.1 == cl2.1 then Wrap (AddClause th2 cl2) else Wrap (AddClause th2 cl) - else Wrap nil. - -Definition ext_cl th cl k v := - let: (ij, kvs) := cl in set_cl (Clause ij (AndLit kvs (Lit k.+1 v))) th. - -Definition wf_ext_cl cl k rk := (k \notin unzip1 cl.2) && (k < rk)%N. - -Definition wf_fill k kvs := (size kvs == k) && (norm_cl kvs < 3)%N. - -Lemma ext_clP cl1 th k v (cl1k := (cl1.1, (k, v) :: cl1.2)) : - cl1 \in th -> - exists2 th1, ext_cl th cl1 k v = Wrap th1 - & cl1k \in th1 - /\ th1 =i [pred cl | if cl.1 == cl1.1 then cl == cl1k else cl \in th]. -Proof. -case: cl1 => ij kvs /= in cl1k * => th_cl1; set th1p := [pred cl | _]. -pose th1 := [seq if cl.1 == ij then cl1k else cl | cl <- th]. -exists th1; first by elim: (th) @th1 => //= cl th' ->; rewrite -2!fun_if. -suffices Dth1: th1 =i th1p by rewrite Dth1 !inE !eqxx. -move=> cl; rewrite inE; apply/mapP/idP=> [[{cl}cl th_cl ->] | ]. - by case cl_ij: (cl.1 == ij); rewrite ?eqxx ?cl_ij. -case: ifP => [_ /eqP-> | cl'ij th_cl]; last by exists cl; rewrite ?cl'ij. -by exists (ij, kvs); rewrite ?eqxx. -Qed. - -(* Satisfiability tests. *) - -Definition sat_test (rO : rel clause) ij12 th := - if get_cl (Ref ij12.1) th is Some cl1 then - oapp (rO cl1) true (get_cl (Ref ij12.2) th) - else true. - -(* This reflects the application of (3.5.1) for an arbitrary pair of entries. *) -Definition Otest cl1 cl2 := - let: (ij1, kvs1) := cl1 in let: (ij2, kvs2) := cl2 in - let fix loop s1 s2 kvs2 := - if kvs2 is (k, v2) :: kvs2 then - if get_lit k kvs1 is Some v1 then loop (v1 * v2 + s1) s2 kvs2 else - loop s1 s2.+1 kvs2 - else (s1, if norm_cl kvs1 == 3 then 0%N else s2) in - let: (s1, s2) := loop 0 0%N kvs2 in - (norm_cl kvs2 == 3) ==> (`|s1 - dot_ref ij1 ij2| <= s2)%N. - -(* Matching up to a permutation of the rows, columns, and base vectors. *) - -Definition sub_match th1 th2 := - let match_cl cl1 cl2 := - if cl2.1 == cl1.1 then subseq cl1.2 cl2.2 else false in - all [pred cl1 | has (match_cl cl1) th2] th1. - -Definition wf_consider ij th (ri := (th_bbox th).1) := - (ij.1 < 2 + ((2 < ri) || sub_match th (tr_th th)).*2)%N && (ij.2 < 2)%N. - -CoInductive sym := Sym (si : seq nat) (sj : seq nat) (sk : seq nat). - -Definition sym_match s th1 th2 := - let: Sym si sj sk := s in let: (ri, rj, rk) := (th_bbox th1, th_dim th1) in - let is_sym r s := uniq s && all (gtn r) s in - let match_cl cl2 := - let: (i2, j2, kvs2) := cl2 in let ij := (nth ri si i2, nth rj sj j2) in - let match_lit kvs1 kv := (nth rk sk kv.1, kv.2) \in kvs1 in - let match_cl1 cl1 := - let: (ij1, kvs1) := cl1 in (ij1 == ij) && all (match_lit kvs1) kvs2 in - uniq (unzip1 kvs2) && has match_cl1 th1 in - [&& is_sym ri si, is_sym rj sj, is_sym rk sk & all match_cl th2]. - -(* Try to compute the base vector permutation for a given row and column *) -(* permutation. We assume each base vector is determined by the entries of *) -(* which it is a proper constituent, and that there are at most two columns. *) -Definition find_sym_k th1 th2 (si sj : seq nat) := - let store_lit c kv ksig := - let: (k, v) := kv in if v == 0 then ksig else let cv := (c, v) in - let fix insert_in (cvs : seq (nat * int)) := - if cvs is cv' :: cvs' then - if (c < cv'.1)%N then cv :: cvs else cv' :: insert_in cvs' - else [:: cv] in - set_nth nil ksig k (insert_in (nth nil ksig k)) in - let fix read_lit ksig1 ksig2 := - if ksig1 is cvs :: ksig1' then - let k := index cvs ksig2 in - k :: read_lit ksig1' (set_nth nil ksig2 k nil) - else nil in - let fix store2 ksig1 ksig2 cls1 := - if cls1 is (i1, j1, kvs1) :: cls1' then - if get_cl (nth 0 si i1, nth 0 sj j1)%N th2 is Some (_, kvs2) then - let st_kvs := foldr (store_lit (i1.*2 + j1)%N) in (* assume j1 <= 1 *) - store2 (st_kvs ksig1 kvs1) (st_kvs ksig2 kvs2) cls1' - else None - else - let sk := read_lit ksig1 ksig2 in - if all (gtn (size ksig2)) sk then Some (Sym si sj sk) else None in - store2 nil nil th1. - -(* Try to find a symmetry that maps th1 to th2, assuming the same number of *) -(* rows and columns, and considering at most one row exchange. *) -Definition find_sym th1 th2 := - let: (ri, rj) := th_bbox th2 in let si := iota 0 ri in let sj := iota 0 rj in - if find_sym_k th1 th2 si sj is Some _ as s then s else - let fix loop m := - if m is i.+1 then - let fix inner_loop m' := - if m' is i'.+1 then - let si' := (set_nth 0 (set_nth 0 si i i') i' i)%N in - if find_sym_k th1 th2 si' sj is Some _ as s then s else inner_loop i' - else None in - if inner_loop i is Some _ as s then s else loop i - else None in - loop ri. - -Section Interpretation. - -Variables (gT : finGroupType) (G : {group gT}). - -Definition is_Lmodel bb b := - [/\ [/\ odd bb.1.+1, odd bb.2.+1, bb.1 > 1, bb.2 > 1 & bb.1 != bb.2]%N, - forall ij, b ij \in 'Z[irr G] - & {in wf_ref bb &, forall ij1 ij2, '[b ij1, b ij2] = (dot_ref ij1 ij2)%:R}]. - -Definition is_Rmodel X := orthonormal X /\ {subset X <= 'Z[irr G]}. - -Inductive model := Model bb f X of is_Lmodel bb f & is_Rmodel X. - -Coercion model_bbox m := let: Model d _ _ _ _ := m in d. -Definition model_entry m := let: Model _ f _ _ _ := m in f. -Coercion model_entry : model >-> Funclass. -Coercion model_basis m := let: Model _ _ X _ _ := m in X. -Lemma LmodelP (m : model) : is_Lmodel m m. Proof. by case: m. Qed. -Lemma RmodelP (m : model) : is_Rmodel m. Proof. by case: m. Qed. - -Fact nil_RmodelP : is_Rmodel nil. Proof. by []. Qed. - -Definition eval_cl (m : model) kvs := \sum_(kv <- kvs) m`_kv.1 *~ kv.2. - -Definition sat_lit (m : model) ij kv := '[m ij, m`_kv.1] == kv.2%:~R. -Definition sat_cl m cl := uniq (unzip1 cl.2) && all (sat_lit m cl.1) cl.2. - -Definition sat (m : model) th := - [&& sub_bbox (th_bbox th) m, th_dim th <= size m & all (sat_cl m) th]%N. -Definition unsat th := forall m, ~ sat m th. - -Lemma satP (m : model) th : - reflect {in th, forall cl, - [/\ cl.1 \in wf_ref m, uniq (unzip1 cl.2) - & {in cl.2, forall kv, kv.1 < size m /\ sat_lit m cl.1 kv}%N]} - (sat m th). -Proof. -apply: (iffP and3P) => [[/th_bboxP thbP /th_dimP thdP /allP thP] cl th_cl |thP]. - have /andP[-> clP] := thP _ th_cl; split=> // [|kv cl_kv]; first exact: thbP. - by rewrite (thdP _ th_cl) ?(allP clP). -split; first by apply/th_bboxP=> cl /thP[]. - by apply/th_dimP=> cl /thP[_ _ clP] kv /clP[]. -by apply/allP=> cl /thP[_ Ucl clP]; rewrite /sat_cl Ucl; apply/allP=> kv /clP[]. -Qed. -Arguments satP [m th]. - -(* Reflexion of the dot product. *) - -Lemma norm_clP m th cl : - sat m th -> cl \in th -> - let norm := norm_cl cl.2 in let beta := m cl.1 in - [/\ (norm <= 3)%N, norm == 3 -> beta = eval_cl m cl.2 - & (norm < 3)%N -> size cl.2 == size m -> - exists2 dk, dk \in dirr_constt beta & orthogonal (dchi dk) m]. -Proof. -case: cl => ij kvs /satP thP /thP[wf_ij Uks clP] norm beta. -have [[_ ZmL Dm] [o1m ZmR]] := (LmodelP m, RmodelP m). -set ks := unzip1 kvs in Uks; pose Aij := [seq m`_k | k <- ks]. -have lt_ks k: k \in ks -> (k < size m)%N by case/mapP=> kv /clP[ltk _] ->. -have sAm: {subset Aij <= (m : seq _)} - by move=> _ /mapP[k /lt_ks ltk ->]; rewrite mem_nth. -have o1Aij: orthonormal Aij. - have [Um _] := orthonormalP o1m; apply: sub_orthonormal o1m => //. - rewrite map_inj_in_uniq // => k1 k2 /lt_ks ltk1 /lt_ks ltk2 /eqP. - by apply: contraTeq; rewrite nth_uniq. -have [X AijX [Y [defXY oXY oYij]]] := orthogonal_split Aij beta. -have{AijX} defX: X = \sum_(xi <- Aij) '[beta, xi] *: xi. - have [_ -> ->] := orthonormal_span o1Aij AijX; apply: eq_big_seq => xi CFxi. - by rewrite defXY cfdotDl (orthoPl oYij) ?addr0. -have ->: eval_cl m kvs = X. - rewrite {}defX !big_map; apply: eq_big_seq => kv /clP[_ /eqP->]. - by rewrite scaler_int. -rewrite -leC_nat -ltC_nat -eqC_nat /=. -have <-: '[beta] = 3%:R by rewrite Dm // /dot_ref !eqxx. -have <-: '[X] = norm%:R. - rewrite {}defX {}/norm cfnorm_sum_orthonormal // {o1Aij oYij sAm}/Aij. - transitivity (\sum_(kv <- kvs) `|kv.2%:~R| ^+ 2 : algC). - by rewrite !big_map; apply: eq_big_seq => kv /clP[_ /eqP->]. - rewrite unlock /=; elim: (kvs) => //= [[k v] kvs' ->]. - by rewrite -intr_norm -natrX -natrD. -rewrite defXY cfnormDd //; split; first by rewrite ler_paddr ?cfnorm_ge0. - by rewrite eq_sym addrC -subr_eq0 addrK cfnorm_eq0 => /eqP->; rewrite addr0. -have{ZmL} Zbeta: beta \in 'Z[irr G] by apply: ZmL. -have Z_X: X \in 'Z[irr G]. - rewrite defX big_seq rpred_sum // => xi /sAm/ZmR Zxi. - by rewrite rpredZ_Cint ?Cint_cfdot_vchar. -rewrite -ltr_subl_addl subrr cnorm_dconstt; last first. - by rewrite -[Y](addKr X) -defXY addrC rpredB. -have [-> | [dk Ydk] _ /eqP sz_kvs] := set_0Vmem (dirr_constt Y). - by rewrite big_set0 ltrr. -have Dks: ks =i iota 0 (size m). - have: {subset ks <= iota 0 (size m)} by move=> k /lt_ks; rewrite mem_iota. - by case/leq_size_perm=> //; rewrite size_iota size_map sz_kvs. -suffices o_dk_m: orthogonal (dchi dk) m. - exists dk; rewrite // dirr_consttE defX cfdotDl cfdot_suml. - rewrite big1_seq ?add0r -?dirr_consttE // => xi /sAm CFxi. - by rewrite cfdotC cfdotZr (orthoPl o_dk_m) // mulr0 conjC0. -apply/orthoPl=> _ /(nthP 0)[k ltk <-]; have [Um o_m] := orthonormalP o1m. -have Z1k: m`_k \in dirr G by rewrite dirrE ZmR ?o_m ?eqxx ?mem_nth. -apply: contraTeq Ydk => /eqP; rewrite dirr_consttE cfdot_dirr ?dirr_dchi //. -have oYm: '[Y, m`_k] = 0 by rewrite (orthoPl oYij) ?map_f // Dks mem_iota. -by do 2?case: eqP => [-> | _]; rewrite // ?cfdotNr oYm ?oppr0 ltrr. -Qed. - -Lemma norm_cl_eq3 m th cl : - sat m th -> cl \in th -> norm_cl cl.2 == 3 -> m cl.1 = eval_cl m cl.2. -Proof. by move=> m_th /(norm_clP m_th)[]. Qed. - -Lemma norm_lit m th cl kv : - sat m th -> cl \in th -> kv \in cl.2 -> (`|kv.2| <= 1)%N. -Proof. -move=> m_th /(norm_clP m_th)[cl_le3 _ _]. -elim: cl.2 => //= [[k v] kvs IHkvs] in cl_le3 * => /predU1P[-> | /IHkvs->//]. - by apply: contraLR cl_le3; rewrite -ltnNge -leq_sqr => /subnKC <-. -exact: leq_trans (leq_addl _ _) cl_le3. -Qed. - -(* Decision procedure framework (in which we will define O and L). *) - -Definition is_sat_test (tO : pred theory) := forall m th, sat m th -> tO th. - -Lemma sat_testP (rO : rel clause) ij12 : - (forall m th cl1 cl2, sat m th -> cl1 \in th -> cl2 \in th -> rO cl1 cl2) -> - is_sat_test (sat_test rO ij12). -Proof. -rewrite /sat_test => O m th /O O_th; case: get_clP => // cl1 [th_cl1 _]. -by case: get_clP => // cl2 [th_cl2 _]; apply: O_th. -Qed. - -(* Case analysis on the value of a specific projection. *) - -Definition lit_vals : seq int := [:: 0; 1; -1]. - -Lemma sat_cases (m : model) th k cl : - sat m th -> cl \in th -> wf_ext_cl cl k (size m) -> - exists2 v, v \in lit_vals & sat m (unwrap (ext_cl th cl k v)). -Proof. -case: cl => ij kvs /satP thP th_cl /andP[cl'k ltkm]. -have [[_ ZmL _] [o1m ZmR]] := (LmodelP m, RmodelP m). -have [m_ij Uij clP] := thP _ th_cl. -have /CintP[v Dv]: '[m ij, m`_k] \in Cint. - by rewrite Cint_cfdot_vchar ?ZmL ?ZmR ?mem_nth. -have [/= th1 Dthx [th1_cl Dth1]] := ext_clP k v th_cl. -suffices{Dthx} m_th1: sat m th1. - exists v; last by rewrite /ext_cl Dthx. - by case: (v) (norm_lit m_th1 th1_cl (mem_head _ _)); do 2?case. -apply/satP=> cl1; rewrite Dth1 inE; case: ifP => [_ /eqP-> | _ /thP] //=. -by rewrite cl'k; split=> // kv /predU1P[-> | /clP//]; rewrite /sat_lit Dv. -Qed. -Arguments sat_cases [m th] k [cl]. - -Definition unsat_cases_hyp th0 kvs tO cl := - let: (k, _) := head (2, 0) kvs in let thk_ := ext_cl th0 cl k in - let th's := [seq unwrap (thk_ v) | v <- lit_vals & v \notin unzip2 kvs] in - let add hyp kv := - let: (_, v) := kv in let: Wrap th := thk_ v in hyp /\ unsat th in - foldl add (wf_ext_cl cl k (th_dim th0) && all (predC tO) th's) kvs. - -Lemma unsat_cases th ij kvs tO : - is_sat_test tO -> oapp (unsat_cases_hyp th kvs tO) False (get_cl ij th) -> - unsat th. -Proof. -case: get_clP => //= cl [th_cl _] O; rewrite /unsat_cases_hyp. -case: head => k _; set thk_ := ext_cl th cl k; set add := fun _ _ => _. -set wf_kvs := _ && _; rewrite -[kvs]revK foldl_rev => Ukvs m m_th. -have{Ukvs}: all (fun kv => ~~ sat m (unwrap (thk_ kv.2))) (rev kvs) && wf_kvs. - elim: rev Ukvs => // [[_ v] /= kvs' IH]; case Dthk: (thk_ v) => [thv] [/IH]. - by rewrite -andbA => -> Uthk; rewrite andbT; apply/negP; apply: Uthk. -case/and3P=> /allP Uthkvs /andP[cl'k ltkr] /allP Uthkv's. -have [|{cl'k ltkr} v lit_v m_thv] := sat_cases k m_th th_cl. - by rewrite /wf_ext_cl cl'k (leq_trans ltkr) //; have [] := and3P m_th. -have /idPn[] := O _ _ m_thv; apply: Uthkv's; apply: map_f. -rewrite mem_filter lit_v andbT -mem_rev -map_rev. -by apply: contraL m_thv => /mapP[kv /Uthkvs m'thkv ->]. -Qed. - -(* Dot product reflection. *) - -Lemma O ij12 : is_sat_test (sat_test Otest ij12). -Proof. -apply: sat_testP => m th [ij1 kvs1] [ij2 kvs2] /= m_th th_cl1 th_cl2. -set cl1eq := _ == 3; set cl2eq := _ == 3; have [_ _ Dm] := LmodelP m. -pose goal s1 s2 := cl2eq ==> (`|s1 - (dot_ref ij1 ij2)%:~R| <= s2%:R :> algC). -set kvs := kvs2; set s1 := 0; set s2 := {2}0%N; have thP := satP m_th. -have{thP} [[wf_cl1 _ cl1P] [wf_cl2 _ cl2P]] := (thP _ th_cl1, thP _ th_cl2). -have: goal (s1%:~R + '[m ij1, eval_cl m kvs]) (if cl1eq then 0%N else s2). - apply/implyP=> /(norm_cl_eq3 m_th th_cl2) <-. - by rewrite if_same Dm // addrK normr0. -have /allP: {subset kvs <= kvs2} by []. -rewrite cfdot_sumr unlock; elim: kvs s1 s2 => [|[k v2] kvs IHkvs] s1 s2 /=. - by rewrite addr0 /goal -rmorphB pmulrn -!CintrE. -case/andP=> kvs2_v /IHkvs{IHkvs}IHkvs; have{cl2P} [ltk _] := cl2P _ kvs2_v. -have [v1 /cl1P[_ /eqP/=Dv1] | kvs1'k] := get_litP. - rewrite addrA => gl12; apply: IHkvs; congr (goal (_ + _) _): gl12. - by rewrite raddfMz addrC /= Dv1 -mulrzA -rmorphD. -move=> gl12; apply: IHkvs; case: ifP gl12 => [/(norm_cl_eq3 m_th th_cl1)->|_]. - rewrite cfdot_suml big1_seq ?add0r //= => kv1 kvs1_kv1. - have [[ltk1 _] [/orthonormalP[Um oom] _]] := (cl1P _ kvs1_kv1, RmodelP m). - rewrite -!scaler_int cfdotZl cfdotZr oom ?mem_nth ?nth_uniq // mulrb. - by rewrite ifN ?mulr0 //; apply: contraNneq kvs1'k => <-; apply: map_f. -rewrite /goal -(ler_add2r 1) -mulrSr; case: (cl2eq) => //; apply: ler_trans. -set s := '[_, _]; rewrite -[_ + _](addrK s) (ler_trans (ler_norm_sub _ _)) //. -rewrite 2![_ + s]addrAC addrA ler_add2l {}/s -scaler_int cfdotZr rmorph_int. -have [|v1 _] := sat_cases k m_th th_cl1; first exact/andP. -have [th1 -> /= [th1_cl1 _] m_th1] := ext_clP k v1 th_cl1. -have [_ _ /(_ _ (mem_head _ _))[_ /eqP->]] := satP m_th1 _ th1_cl1. -have ubv1: (`|v1| <= 1)%N := norm_lit m_th1 th1_cl1 (mem_head _ _). -have ubv2: (`|v2| <= 1)%N := norm_lit m_th th_cl2 kvs2_v. -by rewrite -rmorphM -intr_norm lern1 abszM /= (leq_mul ubv2 ubv1). -Qed. - -(* "Without loss" cut rules. *) - -Lemma unsat_wlog cl th : - (let: Wrap th1 := set_cl cl th in (unsat th1 -> unsat th) /\ unsat th1) -> - unsat th. -Proof. by case: set_cl => th1 [Uth /Uth]. Qed. - -Lemma unsat_wlog_cases th1 th2 : - (unsat th1 -> unsat th2) -> unsat th1 -> (true /\ unsat th1) /\ unsat th2. -Proof. by move=> Uth2 Uth1; split; last apply: Uth2. Qed. - -(* Extend the orthonormal basis *) - -Lemma sat_fill m th cl (k := th_dim th) : - sat m th -> cl \in th -> wf_fill k cl.2 -> - exists mr : {CFk | is_Rmodel CFk}, - sat (Model (LmodelP m) (svalP mr)) (unwrap (ext_cl th cl k 1)). -Proof. -move=> m_th th_cl /andP[/eqP sz_kvs n3cl]. -wlog sz_m: m m_th / size m = k. - have lekm: (k <= size m)%N by have [] := and3P m_th. - have mrP: is_Rmodel (take k m). - have [] := RmodelP m; rewrite -{1 2}(cat_take_drop k m) orthonormal_cat /=. - by case/andP=> o1mr _ /allP; rewrite all_cat => /andP[/allP]. - move/(_ (Model (LmodelP m) mrP)); apply; rewrite ?size_takel //. - congr (_ && _): m_th; rewrite lekm size_takel ?leqnn //=. - apply: eq_in_all => cl1 /th_dimP lt_cl1; congr (_ && _). - by apply: eq_in_all => kv1 /lt_cl1 lt_kv1; rewrite /sat_lit nth_take ?lt_kv1. -have [_ _ [//||dk cl_dk o_dk_m]] := norm_clP m_th th_cl. - by rewrite sz_kvs sz_m. -have CFkP: is_Rmodel (rcons m (dchi dk)). - have [o1m /allP Zm] := RmodelP m. - split; last by apply/allP; rewrite all_rcons /= dchi_vchar. - rewrite -cats1 orthonormal_cat o1m orthogonal_sym o_dk_m. - by rewrite /orthonormal /= cfnorm_dchi eqxx. -exists (exist _ _ CFkP); set mk := Model _ _. -have{m_th} mk_th: sat mk th. - congr (_ && _): m_th; rewrite size_rcons sz_m leqnn ltnW //=. - apply: eq_in_all => cl1 /th_dimP lt_cl1; congr (_ && _). - apply: eq_in_all => kv1 /lt_cl1 lt_kv1; congr ('[_, _] == _). - by rewrite nth_rcons sz_m lt_kv1. -have [|{mk_th}v ub_v m_th] := sat_cases k mk_th th_cl. - rewrite /wf_ext_cl size_rcons sz_m (contraFN _ (ltnn k)) //=. - by case/mapP=> kv kv_cl {1}->; rewrite (th_dimP _ _ th_cl). -suffices: 0 < v by case/or4P: ub_v m_th => // /eqP->. -case: (ext_clP k v th_cl) m_th => th1 -> [th1_cl1 _] /and3P[_ _]. -case/allP/(_ _ th1_cl1)/and3P=> _ /eqP/=. -by rewrite nth_rcons sz_m ltnn eqxx CintrE => <- _; rewrite -dirr_consttE. -Qed. - -Lemma unsat_fill ij th : - let fill_cl cl := - if (th_dim th).+1 %/ 1 is k.+1 then - let: Wrap thk := ext_cl th cl k 1 in wf_fill k cl.2 /\ unsat thk - else True in - oapp fill_cl False (get_cl ij th) -> unsat th. -Proof. -rewrite divn1; case: get_clP => //= cl [th_cl _]. -case Dthk: ext_cl => [th1] [wf_thk Uth1] m m_th. -by have [mk] := sat_fill m_th th_cl wf_thk; rewrite Dthk => /Uth1. -Qed. - -(* Matching an assumption exactly. *) - -Lemma sat_exact m th1 th2 : sub_match th1 th2 -> sat m th2 -> sat m th1. -Proof. -move/allP=> s_th12 /satP th2P; apply/satP => cl1 /s_th12/hasP[cl2 th_cl2]. -case: eqP => // <- s_cl12; have [wf_ij2 Ucl2 cl2P] := th2P _ th_cl2. -split=> // [|kv /(mem_subseq s_cl12)/cl2P//]. -by rewrite (subseq_uniq _ Ucl2) ?map_subseq. -Qed. - -Lemma unsat_exact th1 th2 : sub_match th1 th2 -> unsat th1 -> unsat th2. -Proof. by move=> sth21 Uth1 m /(sat_exact sth21)/Uth1. Qed. - -(* Transpose (W1 / W2 symmetry). *) - -Fact tr_Lmodel_subproof (m : model) : is_Lmodel (tr m) (fun ij => m (tr ij)). -Proof. -case: m => /= d f _ [[odd_d1 odd_d2 d1gt1 d2gt1 neq_d12] Zf fP] _. -split=> // [|[j1 i1] [j2 i2]]; first by rewrite eq_sym. -by rewrite ![_ \in _]andbC /= => wf_ij1 wf_ij2; rewrite fP // /dot_ref mulnC. -Qed. - -Definition tr_model m := Model (tr_Lmodel_subproof m) (RmodelP m). - -Lemma sat_tr m th : sat m th -> sat (tr_model m) (tr_th th). -Proof. -move/satP=> thP; apply/satP=> _ /mapP[[[i j] kvs] /thP[m_ij Uks kvsP] ->]. -by rewrite inE /= andbC. -Qed. - -(* Extend the theory (add a new empty clause). *) - -Lemma unsat_consider ij th : - wf_consider ij th -> unsat (AddClause th (& ? in ij)) -> unsat th. -Proof. -case: ij => i j; case/andP; set sym_t := sub_match _ _ => lti ltj Uthij m m_th. -wlog le_m21: m m_th / sym_t -> (m.2 <= m.1)%N. - move=> IH; apply: (IH m m_th) => sym_th. - rewrite leqNgt; apply/negP=> /leqW le_m1_m2. - by have /(sat_exact sym_th)/IH[] := sat_tr m_th. -apply: (Uthij m); congr (_ && _): (m_th) => /=; case: (th_bbox th) => ri rj /=. -have [[odd_m1 _ m1gt1 m2gt1 neq_m12] _ _] := LmodelP m. -rewrite /sub_bbox !geq_max (leq_trans ltj) ?(leq_trans lti) //; case: orP => //. -rewrite -(ltnS 4) (odd_geq _ odd_m1) ltnS. -case=> [/leq_trans-> // | /le_m21]; first by have [/andP[]] := and3P m_th. -by rewrite leq_eqVlt eq_sym (negPf neq_m12); apply: leq_trans. -Qed. - -(* Matching up to a permutation of the rows, columns, and base vectors. *) - -Lemma unsat_match s th1 th2 : sym_match s th1 th2 -> unsat th2 -> unsat th1. -Proof. -pose I_ si mi := si ++ filter [predC si] (iota 0 mi). -have SsP mi si ri (Ii := I_ si mi): - uniq si && all (gtn ri) si -> (ri <= mi)%N -> - [/\ {in Ii, forall i, i < mi}%N, uniq Ii & size Ii = mi]. -- case/andP=> Usi /allP/=ltsi le_ri_mi; have uIm := iota_uniq 0 mi. - have uIi: uniq Ii by rewrite cat_uniq Usi -all_predC filter_all filter_uniq. - have defIi: Ii =i iota 0 mi. - move=> i; rewrite mem_cat mem_filter orb_andr orbN mem_iota. - by apply: orb_idl => /ltsi/leq_trans->. - split=> // [i|]; first by rewrite defIi mem_iota. - by rewrite (perm_eq_size (uniq_perm_eq _ _ defIi)) ?size_iota. -have lt_nth ri si i: (nth ri si i < ri)%N -> (i < size si)%N. - by rewrite !ltnNge; apply: contra => le_si; rewrite nth_default. -case: s => [si sj sk] /= sym12 Uth2 m m_th1; case/and3P: (m_th1) sym12. -case: th_bbox (th_bboxP (bbox_refl (th_bbox th1))) => ri rj rijP. -case/andP=> /= leri lerj lerk _ /and4P[Ssi Ssj /andP[Usk /allP/=lesrk] sym12]. -have{Ssi} /SsP/(_ leri)[ltIi uIi szIi] := Ssi. -have{Ssj SsP} /SsP/(_ lerj)[ltIj uIj szIj] := Ssj. -pose smL ij := m (nth ri (I_ si m.1) ij.1, nth rj (I_ sj m.2) ij.2)%N. -pose smR := [seq m`_k | k <- sk]. -have [[lb_m ZmL Dm] [o1m ZmR]] := (LmodelP m, RmodelP m). -have{lb_m} smLP: is_Lmodel m smL. - split=> // [ij | ij1 ij2 /andP[lti1 ltj1] /andP[lti2 ltj2]]; first exact: ZmL. - by rewrite Dm ?inE /dot_ref/= ?nth_uniq ?ltIi ?ltIj ?mem_nth ?szIi ?szIj. -have{lesrk} ubk k: k \in sk -> (k < size m)%N by move=> /lesrk/leq_trans->. -have smRP: is_Rmodel smR. - have ssmR: {subset smR <= (m : seq _)}. - by move=> _ /mapP[k s_k ->]; rewrite mem_nth ?ubk. - split=> [|xi /ssmR/ZmR//]; have [Um _] := orthonormalP o1m. - apply: sub_orthonormal o1m; rewrite ?map_inj_in_uniq //. - by apply: can_in_inj (index^~ m) _ => k s_k; rewrite /= index_uniq ?ubk. -apply: (Uth2 (Model smLP smRP)); apply/satP=> [][[i2 j2] kvs2] /(allP sym12). -case/andP=> -> /hasP[[[i1 j1] kvs1] th1_cl1 /andP[/eqP[Di1 Dj1] /allP s_kv12]]. -have:= rijP _ th1_cl1; rewrite Di1 Dj1 => /andP[/lt_nth lti1 /lt_nth ltj1]. -rewrite !inE -szIi -szIj !size_cat !(leq_trans _ (leq_addr _ _)) //. -split=> // kv /s_kv12 kvs1_kv1; rewrite size_map /sat_lit /=. -have /lt_nth ltk := th_dimP (leqnn _) _ th1_cl1 _ kvs1_kv1; split=> //. -rewrite (nth_map (th_dim th1)) // /smL !nth_cat lti1 ltj1 -Di1 -Dj1. -by have [_ _ /(_ _ kvs1_kv1)[]] := satP m_th1 _ th1_cl1. -Qed. - -Lemma unsat_sym th1 th2 : - (if find_sym th1 th2 is Some s then sym_match s th2 th1 else false) -> - unsat th1 -> unsat th2. -Proof. by case: find_sym => // s; apply: unsat_match. Qed. - -End Interpretation. - -Arguments satP [gT G m th]. -Arguments unsat [gT G]. -Arguments sat_cases [gT G m th] k [cl]. -Arguments unsat_cases [gT G th] ij kvs [tO]. -Arguments unsat_wlog [gT G]. -Arguments unsat_fill [gT G]. -Arguments unsat_consider [gT G]. -Arguments unsat_match [gT G] s [th1 th2]. - -(* The domain-specific tactic language. *) - -Tactic Notation "consider" constr(ij) := - apply: (unsat_consider ij); first exact isT. - -(* Note that "split" here would be significantly less efficient, because it *) -(* would evaluate the reflected assumption four times. *) -Tactic Notation "fill" constr(ij) := - apply: (unsat_fill ij); apply: (conj isT _). - -Tactic Notation "uwlog" simple_intropattern(IH) ":" constr(cl) := - apply: (unsat_wlog cl); split=> [IH | ]. - -Tactic Notation "uwlog" simple_intropattern(IH) ":" constr(cl) - "by" tactic4(tac) := - apply: (unsat_wlog cl); split=> [IH | ]; first by [tac]. - -Tactic Notation "uhave" constr(kv) "in" constr(ij) - "as" constr(T) constr(ij12) := - apply: (unsat_cases ij [:: kv] (T ij12)); apply: (conj isT _). - -Tactic Notation "uhave" constr(kv1) "," constr(kv2) "in" constr(ij) - "as" constr(T) constr(ij12) := - uhave kv1 in ij as T ij12; uhave kv2 in ij as T ij12. - -Tactic Notation "uhave" constr(kv1) "|" constr(kv2) "in" constr(ij) - "as" constr(T) constr(ij12) := - apply: (unsat_cases ij [:: kv1; kv2] (T ij12)); apply: (conj (conj isT _) _). - -Tactic Notation "uhave" constr(kv1) "|" constr(kv2) "|" constr(kv3) - "in" constr(ij) := - apply: (unsat_cases ij [:: kv1; kv2; kv3] (fun _ _ _ => isT)); - apply: (conj (conj (conj isT _) _) _). - -Tactic Notation "uwlog" simple_intropattern(IH) ":" - constr(kv1) "|" constr(kv2) "in" constr(ij) - "as" constr(T) constr(ij12) := - apply: (unsat_cases ij [:: kv1; kv2] (T ij12)); - apply: unsat_wlog_cases => [IH | ]. - -Tactic Notation "counter" "to" constr(T) constr(ij12) := by move=> ? /(T ij12). - -Tactic Notation "uexact" constr(IH) := apply: unsat_exact IH; exact isT. - -Tactic Notation "symmetric" "to" constr(IH) := apply: unsat_sym (IH); exact isT. - -End CyclicTIisoReflexion. - -Section Three. - -Variables (gT : finGroupType) (G W W1 W2 : {group gT}). -Hypothesis defW : W1 \x W2 = W. - -Let V := cyclicTIset defW. -Let w_ i j := cyclicTIirr defW i j. -Let w1 := #|W1|. -Let w2 := #|W2|. - -Lemma cyclicTIirrC (xdefW : W2 \x W1 = W) i j : - cyclicTIirr xdefW j i = w_ i j. -Proof. by rewrite (dprod_IirrC xdefW defW). Qed. - -Lemma cycTIirrP chi : chi \in irr W -> {i : Iirr W1 & {j | chi = w_ i j}}. -Proof. -case/irrP/sig_eqW=> k ->{chi}. -by have /codomP/sig_eqW[[i j] ->] := dprod_Iirr_onto defW k; exists i, j. -Qed. - -Lemma cycTIirr_aut u i j : w_ (aut_Iirr u i) (aut_Iirr u j) = cfAut u (w_ i j). -Proof. by rewrite /w_ !dprod_IirrE cfAutDprod !aut_IirrE. Qed. - -Let sW1W : W1 \subset W. Proof. by have /mulG_sub[] := dprodW defW. Qed. -Let sW2W : W2 \subset W. Proof. by have /mulG_sub[] := dprodW defW. Qed. - -Lemma card_cycTIset : #|V| = (w1.-1 * w2.-1)%N. -Proof. -have [_ _ _ tiW12] := dprodP defW. -rewrite cardsD (setIidPr _) ?subUset ?sW1W // cardsU {}tiW12 cards1. -rewrite -(dprod_card defW) -addnBA // -!subn1 -/w1 -/w2 subnDA. -by rewrite mulnBl mulnBr mul1n muln1. -Qed. - -Definition cfCyclicTIset i j := cfDprod defW (1 - 'chi_i) (1 - 'chi_j). -Local Notation alpha_ := cfCyclicTIset. - -Lemma cycTIirr00 : w_ 0 0 = 1. Proof. by rewrite /w_ dprod_Iirr0 irr0. Qed. -Local Notation w_00 := cycTIirr00. - -Lemma cycTIirr_split i j : w_ i j = w_ i 0 * w_ 0 j. -Proof. by rewrite /w_ !dprod_IirrE !irr0 cfDprod_split. Qed. - -Lemma cfker_cycTIl j : W1 \subset cfker (w_ 0 j). -Proof. by rewrite /w_ dprod_IirrE irr0 cfDprod_cfun1l cfker_sdprod. Qed. - -Lemma cfker_cycTIr i : W2 \subset cfker (w_ i 0). -Proof. by rewrite /w_ dprod_IirrE irr0 cfDprod_cfun1r cfker_sdprod. Qed. - -Let cfdot_w i1 j1 i2 j2 : '[w_ i1 j1, w_ i2 j2] = ((i1 == i2) && (j1 == j2))%:R. -Proof. exact: cfdot_dprod_irr. Qed. - -Lemma cfCycTI_E i j : alpha_ i j = 1 - w_ i 0 - w_ 0 j + w_ i j. -Proof. -rewrite -w_00 -[w_ i j]opprK /w_ !dprod_IirrE !irr0 -addrA -opprD -!mulrBl. -by rewrite -mulrBr -!rmorphB. -Qed. -Local Notation alphaE := cfCycTI_E. - -Lemma cfCycTI_vchar i j : alpha_ i j \in 'Z[irr W]. -Proof. by rewrite alphaE rpredD ?rpredB ?rpred1 ?irr_vchar. Qed. - -Definition cfCyclicTIsetBase := - [seq alpha_ ij.1 ij.2 | ij in setX [set~ 0] [set~ 0]]. -Local Notation cfWVbase := cfCyclicTIsetBase. - -Let cfdot_alpha_w i1 j1 i2 j2 : - i2 != 0 -> j2 != 0 -> '[alpha_ i1 j1, w_ i2 j2] = [&& i1 == i2 & j1 == j2]%:R. -Proof. -move=> nzi2 nzj2; rewrite alphaE -w_00 !cfdotDl !cfdotNl !cfdot_w. -by rewrite !(eq_sym 0) (negPf nzi2) (negPf nzj2) /= andbF !subr0 add0r. -Qed. - -Let cfdot_alpha_1 i j : i != 0 -> j != 0 -> '[alpha_ i j, 1] = 1. -Proof. -move=> nzi nzj; rewrite alphaE -w_00 !cfdotDl !cfdotNl !cfdot_w. -by rewrite !eqxx andbT /= (negPf nzi) (negPf nzj) addr0 !subr0. -Qed. - -Let cfnorm_alpha i j : i != 0 -> j != 0 -> '[alpha_ i j] = 4%:R. -Proof. -move=> nzi nzj; rewrite -[4]/(size [:: 1; - w_ i 0; - w_ 0 j; w_ i j]). -rewrite -cfnorm_orthonormal 3?big_cons ?big_seq1 ?addrA -?alphaE //. -rewrite /orthonormal -w_00 /= !cfdotNl !cfdotNr !opprK !oppr_eq0 !cfnorm_irr. -by rewrite !cfdot_w !eqxx /= !(eq_sym 0) (negPf nzi) (negPf nzj) !eqxx. -Qed. - -Lemma cfCycTIbase_free : free cfWVbase. -Proof. -apply/freeP=> s /= s_alpha_0 ij; case def_ij: (enum_val ij) => [i j]. -have /andP[nzi nzj]: (i != 0) && (j != 0). - by rewrite -!in_setC1 -in_setX -def_ij enum_valP. -have:= congr1 (cfdotr (w_ i j)) s_alpha_0; rewrite raddf_sum raddf0 => <-. -rewrite (bigD1 ij) //= nth_image def_ij cfdotZl cfdot_alpha_w // !eqxx mulr1. -rewrite big1 ?addr0 // => ij1; rewrite nth_image -(inj_eq enum_val_inj) def_ij. -case: (enum_val ij1) => i1 j1 /= => ne_ij1_ij. -by rewrite cfdotZl cfdot_alpha_w // mulr_natr mulrb ifN. -Qed. - -(* Further results on alpha_ depend on the assumption that W is cyclic. *) - -Hypothesis ctiW : cyclicTI_hypothesis G defW. - -Let cycW : cyclic W. Proof. by case: ctiW. Qed. -Let oddW : odd #|W|. Proof. by case: ctiW. Qed. -Let tiV : normedTI V G W. Proof. by case: ctiW. Qed. -Let ntV : V != set0. Proof. by case/andP: tiV. Qed. - -Lemma cyclicTIhyp_sym (xdefW : W2 \x W1 = W) : cyclicTI_hypothesis G xdefW. -Proof. by split; rewrite // /cyclicTIset setUC. Qed. - -Let cycW1 : cyclic W1. Proof. exact: cyclicS cycW. Qed. -Let cycW2 : cyclic W2. Proof. exact: cyclicS cycW. Qed. -Let coW12 : coprime w1 w2. Proof. by rewrite -(cyclic_dprod defW). Qed. - -Let Wlin k : 'chi[W]_k \is a linear_char. Proof. exact/irr_cyclic_lin. Qed. -Let W1lin i : 'chi[W1]_i \is a linear_char. Proof. exact/irr_cyclic_lin. Qed. -Let W2lin i : 'chi[W2]_i \is a linear_char. Proof. exact/irr_cyclic_lin. Qed. -Let w_lin i j : w_ i j \is a linear_char. Proof. exact: Wlin. Qed. - -Let nirrW1 : #|Iirr W1| = w1. Proof. exact: card_Iirr_cyclic. Qed. -Let nirrW2 : #|Iirr W2| = w2. Proof. exact: card_Iirr_cyclic. Qed. -Let NirrW1 : Nirr W1 = w1. Proof. by rewrite -nirrW1 card_ord. Qed. -Let NirrW2 : Nirr W2 = w2. Proof. by rewrite -nirrW2 card_ord. Qed. - -Lemma cycTI_nontrivial : W1 :!=: 1%g /\ W2 :!=: 1%g. -Proof. -apply/andP; rewrite -!cardG_gt1 -!(subn_gt0 1) !subn1 -muln_gt0. -by rewrite -card_cycTIset card_gt0. -Qed. - -Let ntW1 : W1 :!=: 1%g. Proof. by case: cycTI_nontrivial. Qed. -Let ntW2 : W2 :!=: 1%g. Proof. by case: cycTI_nontrivial. Qed. -Let oddW1 : odd w1. Proof. exact: oddSg oddW. Qed. -Let oddW2 : odd w2. Proof. exact: oddSg oddW. Qed. -Let w1gt2 : (2 < w1)%N. Proof. by rewrite odd_gt2 ?cardG_gt1. Qed. -Let w2gt2 : (2 < w2)%N. Proof. by rewrite odd_gt2 ?cardG_gt1. Qed. - -Let neq_w12 : w1 != w2. -Proof. -by apply: contraTneq coW12 => ->; rewrite /coprime gcdnn -(subnKC w2gt2). -Qed. - -Let cWW : abelian W. Proof. exact: cyclic_abelian. Qed. -Let nsVW : V <| W. Proof. by rewrite -sub_abelian_normal ?subsetDl. Qed. -Let sWG : W \subset G. Proof. by have [_ /subsetIP[]] := normedTI_P tiV. Qed. -Let sVG : V \subset G^#. Proof. by rewrite setDSS ?subsetU ?sub1G. Qed. - -Let alpha1 i j : alpha_ i j 1%g = 0. -Proof. by rewrite cfDprod1 !cfunE cfun11 lin_char1 // subrr mul0r. Qed. - -(* This first part of Peterfalvi (3.4) will be used in (4.10) and (13.9). *) -Lemma cfCycTI_on i j : alpha_ i j \in 'CF(W, V). -Proof. -apply/cfun_onP=> x; rewrite !inE negb_and negbK orbC. -case/or3P => [/cfun0->// | W1x | W2x]. - by rewrite -[x]mulg1 cfDprodE // !cfunE cfun11 lin_char1 ?subrr ?mulr0. -by rewrite -[x]mul1g cfDprodE // !cfunE cfun11 lin_char1 ?subrr ?mul0r. -Qed. - -(* This is Peterfalvi (3.4). *) -Lemma cfCycTIbase_basis : basis_of 'CF(W, V) cfWVbase. -Proof. -rewrite basisEfree cfCycTIbase_free /=. -have ->: \dim 'CF(W, V) = #|V| by rewrite dim_cfun_on_abelian ?subsetDl. -rewrite size_tuple cardsX !cardsC1 nirrW1 nirrW2 -card_cycTIset leqnn andbT. -by apply/span_subvP=> _ /imageP[[i j] _ ->]; apply: cfCycTI_on. -Qed. -Local Notation cfWVbasis := cfCycTIbase_basis. - -Section CyclicTIisoBasis. - -Import CyclicTIisoReflexion ssrint. - -Local Notation unsat := (@unsat gT G). -Local Notation O := (@O gT G). -Local Notation "#1" := (inord 1). - -(* This is the combinatorial core of Peterfalvi (3.5.2). *) -(* Peterfalvi uses evaluation at 1%g to conclude after the second step; since *) -(* this is not covered by our model, we have used the dot product constraints *) -(* between b12 and b11, b21 instead. *) -Let unsat_J : unsat |= & x1 in b11 & -x1 in b21. -Proof. -uwlog b11x1: (& b11 = x1 + x2 + x3) by do 2!fill b11. -uwlog b21x1: (& b21 = -x1 + x2 + x3) by uhave x2, x3 in b21 as O(21, 11). -consider b12; uhave -x2 | x2 | ~x2 in b12. -- by uhave x1 in b12 as O(12, 11); counter to O(12, 21). -- uhave x1 | ~x1 in b12 as O(12, 21). - by uhave ~x3 in b12 as O(12, 21); counter to O(12, 11). - by uhave ~x3 in b12 as O(12, 11); counter to O(12, 21). -uhave x3 | ~x3 in b12 as O(12, 11). - by uhave x1 in b12 as O(12, 21); counter to O(12, 11). -by uhave x1 in b12 as O(12, 11); counter to O(12, 21). -Qed. - -Let unsat_II: unsat |= & x1, x2 in b11 & x1, x2 in b21. -Proof. by fill b11; uhave -x3 in b21 as O(21, 11); symmetric to unsat_J. Qed. - -(* This reflects the application of (3.5.2), but only to rule out nonzero *) -(* components of the first entry that conflict with positive components of *) -(* the second entry; Otest covers all the other uses of (3.5.2) in the proof. *) -Let Ltest (cl1 cl2 : clause) := - let: (i1, j1, kvs1) := cl1 in let: (i2, j2, kvs2) := cl2 in - let fix loop mm kvs2' := - if kvs2' is (k, v2) :: kvs2'' then - let v1 := odflt 0 (get_lit k kvs1) in - if (v2 != 1) || (v1 == 0) then loop mm kvs2'' else - if (v1 != 1) || mm then false else loop true kvs2'' - else true in - (i1 == i2) (+) (j1 == j2) ==> loop false kvs2. - -Let L ij12 : is_sat_test G (sat_test Ltest ij12). -Proof. -apply: sat_testP => m th [[i1 j1] kvs1] [[i2 j2] kvs2] m_th th_cl1 th_cl2. -wlog eq_j: m th i1 i2 j1 j2 m_th th_cl1 th_cl2 / j1 == j2. - move=> IH; case eq_j: (j1 == j2); first exact: IH m_th th_cl1 th_cl2 eq_j. - case eq_i: (i1 == i2); last by rewrite /= eq_i eq_j. - have /(_ (_, _, _)) mem_trt: _ \in tr_th th := map_f _ _. - by rewrite /= addbC; apply: IH (sat_tr m_th) _ _ eq_i; rewrite ?mem_trt. -apply/implyP; rewrite eq_j addbT => neq_i. -rewrite -[f in f _ kvs2]/(idfun _); set f := idfun _; rewrite /= in f *. -have [/= _ Ukvs2 kvsP] := satP m_th _ th_cl2. -move: Ukvs2; set kvs2' := kvs2; set mm := false. -have /allP: {subset kvs2' <= kvs2} by []. -pose lit12 k := (k, 1) \in kvs1 /\ (k, 1) \in kvs2. -have: mm -> {k | lit12 k & k \notin unzip1 kvs2'} by []. -elim: kvs2' mm => [|[k v2] kvs2' IH] //= mm mmP /andP[kvs2k /IH{IH}IHkvs]. -case/andP=> kvs2'k /IHkvs{IHkvs}IHkvs; case: ifP => [_ | /norP[]]. - by apply/IHkvs=> /mmP[kv kvs12kv /norP[]]; exists kv. -have [v1 /= kvs1k | //] := get_litP; case: eqP => // -> in kvs2k * => _ nz_v1. -case Dbb: (th_bbox th) (th_bboxP (bbox_refl (th_bbox th))) => [ri rj] rijP. -have [/andP[/=lti1r ltj1r] /andP[/=lti2r _]] := (rijP _ th_cl1, rijP _ th_cl2). -have rkP := th_dimP (leqnn _) _ th_cl1; have /= ltkr := rkP _ kvs1k. -have symP := unsat_match (Sym [:: i2; i1] [:: j1] _) _ _ m m_th. -rewrite /= Dbb lti1r lti2r ltj1r inE eq_sym neq_i /= in symP. -have [Dv1 | v1_neq1] /= := altP eqP; first rewrite Dv1 in kvs1k. - case: ifP => [/mmP[k0 [kvs1k0 kvs2k0]] | _]; last by apply: IHkvs; exists k. - case/norP=> k'k0; have [/=] := symP [:: k0; k] _ _ unsat_II. - rewrite inE k'k0 ltkr (rkP _ kvs1k0) /= andbT; apply/andP; split; apply/hasP. - by exists (i1, j1, kvs1) => //=; rewrite eqxx kvs1k kvs1k0. - by exists (i2, j2, kvs2) => //=; rewrite (eqP eq_j) eqxx kvs2k kvs2k0. -have{nz_v1 v1_neq1} Dv1: v1 = -1; last rewrite Dv1 in kvs1k. - by case: (v1) nz_v1 v1_neq1 (norm_lit m_th th_cl1 kvs1k) => [[|[]] | []]. -have[] := symP [:: k] _ _ unsat_J; rewrite /= ltkr !andbT /=; apply/andP; split. - by apply/hasP; exists (i1, j1, kvs1); rewrite //= eqxx kvs1k. -by apply/hasP; exists (i2, j2, kvs2); rewrite //= (eqP eq_j) eqxx kvs2k. -Qed. - -(* This is the combinatorial core of Peterfalvi (3.5.4). *) -(* We have made a few simplifications to the combinatorial analysis in the *) -(* text: we omit the (unused) step (3.5.4.4) entirely, which lets us inline *) -(* step (3.5.4.1) in the proof of (3.5.4.2); we clear the assumptions on b31 *) -(* and b32 before the final step (3.5.4.5), exposing a hidden symmetry. *) -Let unsat_Ii : unsat |= & x1 in b11 & x1 in b21 & ~x1 in b31. -Proof. -uwlog Db11: (& b11 = x1 + x2 + x3) by do 2!fill b11. -uwlog Db21: (& b21 = x1 + x4 + x5). - by uhave ~x2, ~x3 in b21 as L(21, 11); do 2!fill b21; uexact Db21. -uwlog Db31: (& b31 = x2 + x4 + x6). - uwlog b31x2: x2 | ~x2 in b31 as L(31, 11). - by uhave x3 in b31 as O(31, 11); symmetric to b31x2. - uwlog b31x4: x4 | ~x4 in b31 as L(31, 21). - by uhave x5 in b31 as O(31, 21); symmetric to b31x4. - uhave ~x3 in b31 as O(31, 11); uhave ~x5 in b31 as L(31, 21). - by fill b31; uexact Db31. -consider b41; uwlog b41x1: x1 | ~x1 in b41 as L(41, 11). - uwlog Db41: (& b41 = x3 + x5 + x6) => [|{b41x1}]. - uhave ~x2 | x2 in b41 as L(41, 11); last symmetric to b41x1. - uhave ~x4 | x4 in b41 as L(41, 21); last symmetric to b41x1. - uhave x3 in b41 as O(41, 11); uhave x5 in b41 as O(41, 21). - by uhave x6 in b41 as O(41, 31); uexact Db41. - consider b12; uwlog b12x1: x1 | ~x1 in b12 as L(12, 11). - uhave ~x2 | x2 in b12 as L(12, 11); last symmetric to b12x1. - by uhave x3 in b12 as O(12, 11); symmetric to b12x1. - uwlog b12x4: -x4 | ~x4 in b12 as O(12, 21). - by uhave -x5 in b12 as O(12, 21); symmetric to b12x4. - uhave ~x2, ~x3 in b12 as L(12, 11); uhave ~x5 in b12 as O(12, 21). - by uhave x6 in b12 as O(12, 31); counter to O(12, 41). -uwlog Db41: (& b41 = x1 + x6 + x7). - uhave ~x2, ~x3 in b41 as L(41, 11); uhave ~x4, ~x5 in b41 as L(41, 21). - by uhave x6 in b41 as O(41, 31); fill b41; uexact Db41. -consider b32; uwlog Db32: (& b32 = x6 - x7 + x8). - uwlog b32x6: x6 | ~x6 in b32 as L(32, 31). - uhave ~x2 | x2 in b32 as L(32, 31); last symmetric to b32x6. - by uhave x4 in b32 as O(32, 31); symmetric to b32x6. - uhave ~x2, ~x4 in b32 as L(32, 31). - uhave -x7 | ~x7 in b32 as O(32, 41). - uhave ~x1 in b32 as O(32, 41); uhave ~x3 in b32 as O(32, 11). - by uhave ~x5 in b32 as O(32, 21); fill b32; uexact Db32. - uhave -x1 in b32 as O(32, 41). - by uhave x3 in b32 as O(32, 11); counter to O(32, 21). -consider b42; uwlog Db42: (& b42 = x6 - x4 + x5). - uhave ~x6 | x6 in b42 as L(42, 41). - uhave ~x7 | x7 in b42 as L(42, 41); last counter to O(42, 32). - uhave x1 in b42 as O(42, 41); uhave x8 in b42 as O(42, 32). - uhave ~x2 | -x2 in b42 as O(42, 11); last counter to O(42, 21). - by uhave -x3 in b42 as O(42, 11); counter to O(42, 21). - uwlog b42x4: -x4 | ~x4 in b42 as O(42, 31). - by uhave -x2 in b42 as O(42, 31); symmetric to b42x4. - by uhave ~x1 in b42 as L(42, 41); uhave x5 in b42 as O(42, 21); uexact Db42. -uwlog Db32: (& ? in b32); first uexact Db32. -uwlog Db41: (& ? in b41); first uexact Db41. -consider b12; uwlog b12x5: x5 | ~x5 in b12 as L(12, 42). - uhave ~x6 | x6 in b12 as L(12, 42); last by consider b22; symmetric to b12x5. - uhave -x4 in b12 as O(12, 42); uhave x1 in b12 as O(12, 21). - by uhave ~x2 in b12 as L(12, 11); counter to O(12, 31). -uhave ~x6 in b12 as L(12, 42); uhave ~x4 in b12 as O(12, 42). -uhave ~x2 in b12 as O(12, 31). -by uhave -x1 in b12 as O(12, 21); counter to L(12, 11). -Qed. - -Let unsat_C : unsat |= & x1 in b11 & x1 in b21 & x1 in b12. -Proof. -consider b31; uwlog Db21: (& b21 = x1 + x2 + x3) by do 2!fill b21. -uwlog Db12: (& b12 = x1 - x2 + x4). - uwlog b21x2: -x2 | ~x2 in b12 as O(12, 21). - by uhave -x3 in b12 as O(12, 21); symmetric to b21x2. - by uhave ~x3 in b12 as O(12, 21); fill b12; uexact Db12. -uwlog Db31: (& b31 = x1 - x4 + x5). - uhave x1 | ~x1 in b31 as L(31, 21); last uexact unsat_Ii. - uhave ~x2, ~x3 in b31 as L(31, 21). - by uhave -x4 in b31 as O(31, 12); fill b31; uexact Db31. -consider b41; uhave x1 | ~x1 in b41 as L(41, 21); last symmetric to unsat_Ii. -uhave ~x5 in b41 as L(41, 31); uhave ~x4 in b41 as O(41, 31). -by uhave ~x2 in b41 as L(41, 21); counter to O(41, 12). -Qed. - -(* This refinement of Peterfalvi (3.5.4) is the essential part of (3.5.5). *) -Let column_pivot (m : model G) (j0 : 'I_m.2.+1) : - exists dk, forall (i : 'I_m.1.+1) (j : 'I_m.2.+1), - j0 != 0 -> i != 0 -> j != 0 -> '[m (i.-1, j.-1), dchi dk] = (j == j0)%:R. -Proof. -pose t_i (i0 i1 : nat) := [eta id with i0 |-> i1, i1 |-> i0]. -pose t_ij i0 i1 ij : ref := (t_i i0 i1 ij.1, ij.2). -have t_iK i0 i1: involutive (t_i i0 i1). - move=> i /=; have [-> | i0'i] := altP (i =P i0). - by rewrite eqxx; case: eqP. - by have [-> | /negPf->] := altP (i =P i1); rewrite ?eqxx // ifN. -have lt_t_i i0 i1 ri i: (i0 <= i1 < ri)%N -> (t_i i0 i1 i < ri)%N = (i < ri)%N. - case/andP=> le_i01 lti1 /=. - by do 2?case: eqP => [-> | _] //; rewrite ?(leq_trans _ lti1). -have t_mP i0 i1 (m0 : model G): - (i0 <= i1 < m0.1)%N -> is_Lmodel m0 (m0 \o t_ij i0 i1). -- have [lbm0 Zm0 Dm0] := LmodelP m0; split=> //= ij1 ij2 wf_ij1 wf_ij2. - by rewrite Dm0 /dot_ref ?(can_eq (t_iK _ _)) // !inE ?lt_t_i. -pose t_m i0 i1 m0 lti01 := Model (t_mP i0 i1 m0 lti01) (RmodelP m0). -without loss suffices{j0 lt_t_i} IHm: m / - exists dk, {in wf_ref m, forall ij, '[m ij, dchi dk] = (ij.2 == 0%N)%:R}. -- have [_ | nzj0] := altP eqP; first by exists (dirr1 G). - have ltj0: (j0.-1 < m.2)%N by rewrite prednK ?lt0n ?leq_ord. - have{IHm} [dk Ddk] := IHm (tr_model (t_m 0%N j0.-1 (tr_model m) ltj0)). - exists dk => i j _ nzi nzj; rewrite -[j.-1](t_iK 0%N j0.-1). - rewrite (Ddk (_, _)) ?inE ?lt_t_i // ?prednK ?lt0n ?leq_ord //. - by rewrite (inv_eq (t_iK _ _)) -eqSS !prednK ?lt0n. -pose cl11 := & b11 = x1 + x2 + x3. -without loss m_th: m / sat m |= cl11 & ? in b21. - move=> IHm; suffices{IHm}: sat m |= & ? in b11 & ? in b21. - have fill_b11 := sat_fill _ (mem_nth cl11 (_ : 1 < _))%N. - by do 3![case/fill_b11=> // ?]; apply: IHm. - have [[_ _ m1gt2 /ltnW m2gt0 _] _ _] := LmodelP m. - by rewrite /sat /= -!andbA /= m2gt0 -(subnKC m1gt2). -without loss{m_th} m_th: m / sat m |= & x1 in b11 & x1 in b21. - pose sat123P := @allP _ (fun k => sat_lit m _ (k, _)) (rev (iota 0 3)). - have [m123 | ] := altP (sat123P b21 0). - suffices: sat m |= cl11 & ~x1, ~x2, ~x3 in b21 by move/(O(21, 11)). - by rewrite /sat /= {1}/sat_cl /= !m123. - case/allPn=> k k012 /negP nz_m21 IHm; rewrite -[sat_lit _ _ _]andbT in nz_m21. - have ltk3: (k < 3)%N by rewrite mem_rev mem_iota in k012. - have [[/andP[/allP/=n1m _] Zm] [_ /= m_gt2 _]] := (RmodelP m, and3P m_th). - have ltk := leq_trans ltk3 m_gt2. - have{n1m Zm} mkP: is_Rmodel [:: m`_k]. - by split=> [|_ /predU1P[->|//]]; rewrite /orthonormal /= ?n1m ?Zm ?mem_nth. - pose mk := Model (LmodelP m) mkP; apply: {IHm}(IHm mk). - have{m_th} [v lit_v m_th] := sat_cases k m_th (mem_head _ _) ltk. - suffices: sat mk |= & x1 in b11 & (Lit 1 v) in b21. - by case/or4P: lit_v m_th => // /eqP-> => [/and4P[] | | _ /(L(21,11))]. - have [m_bb _ m_b21 /sat123P m_b11 _] := and5P m_th. - by apply/and5P; split; rewrite // /sat_cl /= [sat_lit _ _ _]m_b11. -have /dIrrP[dk Ddk]: m`_0 \in dirr G. - have [[/andP[/allP n1m _] Zm] [_ m_gt0 _]] := (RmodelP m, and3P m_th). - by rewrite dirrE Zm ?[_ == 1]n1m ?mem_nth. -exists dk => [][i j] /andP[/= lti ltj]; apply/eqP. -suffices{dk Ddk}: sat_cl m (& (Lit 1 (j == 0))%N in (i, j)). - by rewrite /sat_cl /= andbT /sat_lit Ddk. -without loss{i lti} ->: m i ltj m_th / i = 0%N. - have [bb21_m m_gt0 m11_x1 m21_x1 _] := and5P m_th. - move=> IHi; suffices{IHi} m_i1_x1: sat_lit m (i, 0)%N x1 && true. - apply: (IHi (t_m 0%N i m lti) 0%N); rewrite /sat /sat_cl //= bb21_m m_gt0. - by rewrite /= m_i1_x1 /sat_lit /= andbT /t_ij /=; case: ifP. - case i_gt1: (1 < i)%N; last by case: (i) i_gt1 => [|[|[]]]. - have itv_i: (1 < i < m.1)%N by [apply/andP]; pose m2 := t_m 2 i m itv_i. - have m2_th: sat m2 |= & x1 in b11 & x1 in b21 & ? in b31. - rewrite /sat m_gt0 -andbA (leq_trans _ lti) ?(leq_trans _ ltj) /sat_cl //=. - by rewrite /sat_lit /= -(subnKC i_gt1); have [_ _] := and3P m_th. - have [v] := sat_cases _ m2_th (mem_head _ _) m_gt0; rewrite !inE. - by case/or3P=> /eqP-> => [/unsat_Ii | /and4P[] | /(L(31,11))]. -have [-> | nzj] := posnP j; first by case/and5P: m_th. -without loss{ltj nzj} ->: m j m_th / j = 1%N. - have itv_j: (0 < j < m.2)%N by rewrite nzj. - move/(_ (tr_model (t_m _ j (tr_model m) itv_j)) _ _ (erefl _)) => /=. - by rewrite /sat /sat_cl /sat_lit /= -(prednK nzj) => ->. -have{m_th}[/= _ m_gt0 m_x1] := and3P m_th. -have{m_x1} m_th: sat m |= & x1 in b11 & x1 in b21 & ? in b12. - by rewrite /sat m_gt0 /sub_bbox; have [[_ _ -> ->]] := LmodelP m. -have [v] := sat_cases 0%N m_th (mem_head _ _) m_gt0; rewrite !inE. -by case/or3P=> /eqP-> => [/and4P[] | /unsat_C | /(L(12,11))]. -Qed. - -(* This is Peterfalvi (3.5). *) -(* We have inlined part of the proof of (3.5.5) in this main proof, replacing *) -(* some combinatorial arguments with direct computation of the dot product, *) -(* this avoids the duplicate case analysis required to exploit (3.5.5) as it *) -(* is stated in the text. *) -Lemma cyclicTIiso_basis_exists : - exists xi_ : Iirr W1 -> Iirr W2 -> 'CF(G), - [/\ xi_ 0 0 = 1, forall i j, xi_ i j \in 'Z[irr G], - forall i j, i != 0 -> j != 0 -> - 'Ind (alpha_ i j) = 1 - xi_ i 0 - xi_ 0 j + xi_ i j - & forall i1 j1 i2 j2, '[xi_ i1 j1, xi_ i2 j2] = ((i1, j1) == (i2, j2))%:R]. -Proof. -(* Instantiate the abstract theory vertically and horizontally. *) -pose beta i j : 'CF(G) := 'Ind[G] (alpha_ i j) - 1. -have Zbeta i j: beta i j \in 'Z[irr G]. - by rewrite rpredB ?rpred1 ?cfInd_vchar ?cfCycTI_vchar. -have o_alphaG_1 i j: i != 0 -> j != 0 -> '['Ind[G] (alpha_ i j), 1] = 1. - by move=> nz_i nz_j; rewrite -cfdot_Res_r rmorph1 cfdot_alpha_1. -have o_beta_1 i j: i != 0 -> j != 0 -> '[beta i j, 1] = 0. - by move=> nzi nzj; rewrite cfdotBl o_alphaG_1 // cfnorm1 subrr. -have o_beta i1 j1 i2 j2 : i1 != 0 -> j1 != 0 -> i2 != 0 -> j2 != 0 -> - '[beta i1 j1, beta i2 j2] = ((i1 == i2).+1 * (j1 == j2).+1 - 1)%:R. -- move=> nzi1 nzj1 nzi2 nzj2; rewrite mulSnr addnS mulnSr /=. - rewrite cfdotBr o_beta_1 // subr0 cfdotBl (cfdotC 1) o_alphaG_1 //. - rewrite (normedTI_isometry tiV) ?cfCycTI_on // rmorph1 addrC. - rewrite (alphaE i2) cfdotDr !cfdotBr cfdot_alpha_1 // -!addrA addKr addrA. - rewrite addrC cfdot_alpha_w // subn1 -addnA !natrD mulnb; congr (_ + _). - rewrite alphaE -w_00 !(cfdotBl, cfdotDl) !cfdot_w !eqxx !(eq_sym 0). - rewrite (negPf nzi1) (negPf nzj1) (negPf nzi2) (negPf nzj2) /= !andbF !andbT. - by rewrite !addr0 !subr0 !opprB !subr0. -pose beta_fun := [fun ij => beta (inord ij.1.+1) (inord ij.2.+1)]. -have beta_modelP: is_Lmodel ((Nirr W1).-1, (Nirr W2).-1) beta_fun. - split=> [ | //= | ij1 ij2 /=/andP[lti1 ltj1] /andP[lti2 ltj2]]. - by rewrite -!(ltnS 2) -eqSS NirrW1 NirrW2. - by rewrite o_beta -?val_eqE /= ?inordK. -pose beta_model := Model beta_modelP (nil_RmodelP G). -have betaE i j: i != 0 -> j != 0 -> beta i j = beta_fun (i.-1, j.-1). - by move=> nzi nzj /=; rewrite !prednK ?lt0n ?inord_val. -have /fin_all_exists [dXi0 betaXi0] i0: exists dX, i0 != 0 -> - forall i j, i != 0 -> j != 0 -> '[beta i j, dchi dX] = (i == i0)%:R. -- have [/= dX DdX] := @column_pivot (tr_model beta_model) i0. - by exists dX => nzi0 i j nzi nzj; rewrite betaE ?DdX. -have /fin_all_exists [dX0j betaX0j] j0: exists dX, j0 != 0 -> - forall i j, i != 0 -> j != 0 -> '[beta i j, dchi dX] = (j == j0)%:R. -- have [dX DdX] := @column_pivot beta_model j0. - by exists dX => nzj0 i j nzi nzj; rewrite betaE ?DdX. -pose Xi0 j := dchi (dXi0 j); pose X0j i := dchi (dX0j i). -(* Construct the orthonormal family xi_ i j. *) -pose xi_ i j := if i == 0 then if j == 0 then 1 else - X0j j else - if j == 0 then - Xi0 i else beta i j - Xi0 i - X0j j. -exists xi_; split=> [| i j | i j nzi nzj | i1 j1 i2 j2]. -- by rewrite /xi_ !eqxx. -- rewrite /xi_; do 2!case: ifP => _; rewrite ?rpred1 ?rpredN ?dchi_vchar //. - by rewrite 2?rpredB ?dchi_vchar. -- by rewrite /xi_ /= !ifN // addrCA subrK addrACA subrK addrA addrK. -have o_dchi i j dk1 dk2 (phi := beta i j): - '[phi, dchi dk1] = 1 -> '[phi, dchi dk2] = 0 -> '[dchi dk1, dchi dk2] = 0. -- move=> phi1 phi0; have /eqP: 1 != 0 :> algC := oner_neq0 _. - rewrite -phi1 cfdot_dchi; do 2!case: eqP => [->|_]; rewrite ?subrr //. - by rewrite dchi_ndirrE cfdotNr phi0 oppr0. -have [nzi01 nzj01] := (Iirr1_neq0 ntW1, Iirr1_neq0 ntW2). -have X0j_1 j: j != 0 -> '[X0j j, 1] = 0. - by move=> nzj; rewrite -dchi1 (o_dchi #1 j) ?betaX0j ?eqxx ?dchi1 ?o_beta_1. -have Xi0_1 i: i != 0 -> '[Xi0 i, 1] = 0. - by move=> nzi; rewrite -dchi1 (o_dchi i #1) ?betaXi0 ?eqxx ?dchi1 ?o_beta_1. -have Xi0_X0j i j: i != 0 -> j != 0 -> '[Xi0 i, X0j j] = 0. - move=> nzi nzj; pose j' := conjC_Iirr j. - apply: (o_dchi i j'); rewrite (betaX0j, betaXi0) ?conjC_Iirr_eq0 ?eqxx //. - by rewrite -(inj_eq irr_inj) conjC_IirrE mulrb ifN ?odd_eq_conj_irr1 ?irr_eq1. -have X0j_X0j j j0: j != 0 -> j0 != 0 -> '[X0j j, X0j j0] = (j == j0)%:R. - move=> nzj nzj0; case: (altP eqP) => [-> | j0'j]; first exact: cfnorm_dchi. - by apply: (o_dchi #1 j); rewrite ?betaX0j ?eqxx ?(negPf j0'j). -have Xi0_Xi0 i i0: i != 0 -> i0 != 0 -> '[Xi0 i, Xi0 i0] = (i == i0)%:R. - move=> nzi nzi0; case: (altP eqP) => [-> | i0'i]; first exact: cfnorm_dchi. - by apply: (o_dchi i #1); rewrite ?betaXi0 ?eqxx ?(negPf i0'i). -have oxi_00 i j: '[xi_ i j, xi_ 0 0] = ((i == 0) && (j == 0))%:R. - rewrite /xi_; case: ifPn => [_ | nzi]. - by case: ifPn => [_ | nzj]; rewrite ?cfnorm1 // cfdotNl X0j_1 ?oppr0. - case: ifPn => [_ | nzj]; first by rewrite cfdotNl Xi0_1 ?oppr0. - by rewrite 2!cfdotBl o_beta_1 ?X0j_1 ?Xi0_1 ?subr0. -have oxi_0j i j j0: '[xi_ i j, xi_ 0 j0] = ((i == 0) && (j == j0))%:R. - rewrite /xi_; have [-> | nzj0] := altP (j0 =P 0); first exact: oxi_00. - rewrite cfdotNr; case: ifPn => [_ | nzi]. - have [-> | nzj] := altP eqP; last by rewrite cfdotNl opprK X0j_X0j. - by rewrite cfdotC X0j_1 // conjC0 oppr0 mulrb ifN_eqC. - have [_ | nzj] := ifPn; first by rewrite cfdotNl Xi0_X0j ?oppr0. - by rewrite 2!cfdotBl Xi0_X0j // subr0 betaX0j ?X0j_X0j // subrr oppr0. -have{oxi_00} oxi_i0 i j i0: '[xi_ i j, xi_ i0 0] = ((i == i0) && (j == 0))%:R. - rewrite /xi_; have [-> | nzi0] := altP (i0 =P 0); first exact: oxi_00. - rewrite cfdotNr andbC; have [_ | nzj] := boolP (j == 0). - have [-> | nzi] := altP eqP; last by rewrite cfdotNl opprK Xi0_Xi0. - by rewrite cfdotC Xi0_1 // conjC0 oppr0 mulrb ifN_eqC. - have [_ | nzi] := ifPn; first by rewrite cfdotNl opprK cfdotC Xi0_X0j ?conjC0. - rewrite 2!cfdotBl betaXi0 ?Xi0_Xi0 // subrr add0r opprK. - by rewrite cfdotC Xi0_X0j // conjC0. -have [-> | nzi2] := altP (i2 =P 0); first exact: oxi_0j. -have [-> | nzj2] := altP (j2 =P 0); first exact: oxi_i0. -rewrite cfdotC eq_sym; apply: canLR (@conjCK _) _; rewrite rmorph_nat. -have [-> | nzi1] := altP (i1 =P 0); first exact: oxi_0j. -have [-> | nzj1] := altP (j1 =P 0); first exact: oxi_i0. -have ->: xi_ i1 j1 = beta i1 j1 + xi_ i1 0 + xi_ 0 j1 by rewrite /xi_ !ifN. -rewrite 2!cfdotDr oxi_i0 oxi_0j andbC /xi_ (negPf nzi2) (negPf nzj2) !addr0. -rewrite eq_sym xpair_eqE cfdotC 2!cfdotBr o_beta // betaXi0 ?betaX0j //. -by rewrite -!CintrE /= rmorph_int; do 2!case: (_ == _). -Qed. - -End CyclicTIisoBasis. - -(* This is PeterFalvi, Theorem (3.2)(a, b, c). *) -Theorem cyclicTIiso_exists : - {sigma : 'Hom(cfun_vectType W, cfun_vectType G) | - [/\ {in 'Z[irr W], isometry sigma, to 'Z[irr G]}, sigma 1 = 1 - & {in 'CF(W, V), forall phi : 'CF(W), sigma phi = 'Ind[G] phi}]}. -Proof. -pose sigmaVP f := ('CF(W, V) <= lker (linfun f - linfun 'Ind[G]))%VS. -pose sigmaP f := [&& orthonormal (map f (irr W)), f 1 == 1 & sigmaVP f]. -pose sigma_base f := [seq (dchi (f k) : 'CF(G)) | k : Iirr W]. -pose sigma_spec f := sigmaP (sval (linear_of_free (irr W) (sigma_base f))). -suffices /sigW[f /and3P[]]: exists f : {ffun _}, sigma_spec f. - case: linear_of_free => /=sigma Dsigma o1sigma /eqP sigma1 /eqlfun_inP sigmaV. - exists (linfun sigma); split=> [|| phi /sigmaV]; try by rewrite !lfunE. - do [rewrite size_map !size_tuple => /(_ (irr_free W) (card_ord _))] in Dsigma. - have [inj_sigma dot_sigma] := orthonormalP o1sigma. - rewrite -(map_tnth_enum (irr W)) -map_comp in Dsigma inj_sigma. - move/eq_in_map in Dsigma; move/injectiveP in inj_sigma. - split=> [|_ /zchar_tuple_expansion[z Zz ->]]. - apply: isometry_in_zchar=> _ _ /irrP[k1 ->] /irrP[k2 ->] /=. - by rewrite !lfunE dot_sigma ?map_f ?mem_irr // cfdot_irr (inj_eq inj_sigma). - rewrite linear_sum rpred_sum // => k _; rewrite linearZ rpredZ_Cint //=. - by rewrite -tnth_nth lfunE [sigma _]Dsigma ?mem_enum ?dchi_vchar. -have [xi_ [xi00 Zxi Dxi o1xi]] := cyclicTIiso_basis_exists. -pose f := [ffun k => dirr_dIirr (prod_curry xi_) (inv_dprod_Iirr defW k)]. -exists f; apply/and3P; case: linear_of_free => /= sigma Dsigma. -have{f Dsigma} Deta i j: sigma (w_ i j) = xi_ i j. - rewrite /w_ -tnth_map /= (tnth_nth 0) /=. - rewrite Dsigma ?irr_free //; last by rewrite !size_tuple card_ord. - rewrite nth_mktuple ffunE dprod_IirrK dirr_dIirrE // => {i j} [[i j]] /=. - by rewrite dirrE Zxi o1xi !eqxx. -have sigma1: sigma 1 = 1 by rewrite -w_00 Deta. -rewrite sigma1 /sigmaVP -(span_basis cfWVbasis); split=> //. - rewrite map_orthonormal ?irr_orthonormal //; apply: isometry_in_zchar. - move=> _ _ /cycTIirrP[i1 [j1 ->]] /cycTIirrP[i2 [j2 ->]] /=. - by rewrite !Deta o1xi cfdot_w. -apply/span_subvP=> _ /imageP[[i j] /setXP[nzi nzj] ->]; rewrite !inE in nzi nzj. -rewrite memv_ker !lfun_simp /= subr_eq0 Dxi //. -by rewrite alphaE linearD !linearB sigma1 !Deta. -Qed. - -Fact cyclicTIiso_key : unit. Proof. by []. Qed. -Definition cyclicTIiso := - locked_with cyclicTIiso_key (lfun_linear (sval cyclicTIiso_exists)). -Local Notation sigma := cyclicTIiso. -Let im_sigma := map sigma (irr W). -Let eta_ i j := sigma (w_ i j). - -Lemma cycTI_Zisometry : {in 'Z[irr W], isometry sigma, to 'Z[irr G]}. -Proof. by rewrite [sigma]unlock; case: cyclicTIiso_exists => ? []. Qed. - -Let Isigma : {in 'Z[irr W] &, isometry sigma}. -Proof. by case: cycTI_Zisometry. Qed. -Let Zsigma : {in 'Z[irr W], forall phi, sigma phi \in 'Z[irr G]}. -Proof. by case: cycTI_Zisometry. Qed. - -Lemma cycTIisometry : isometry sigma. -Proof. -move=> phi psi; have [[a ->] [b ->]] := (cfun_irr_sum phi, cfun_irr_sum psi). -rewrite !linear_sum !cfdot_suml; apply: eq_bigr => i _. -rewrite !cfdot_sumr; apply: eq_bigr => j _. -by rewrite !linearZ !cfdotZl !cfdotZr /= Isigma ?irr_vchar. -Qed. - -Lemma cycTIiso_vchar i j : eta_ i j \in 'Z[irr G]. -Proof. by rewrite Zsigma ?irr_vchar. Qed. - -Lemma cfdot_cycTIiso i1 i2 j1 j2 : - '[eta_ i1 j1, eta_ i2 j2] = ((i1 == i2) && (j1 == j2))%:R. -Proof. by rewrite cycTIisometry. Qed. - -Lemma cfnorm_cycTIiso i j : '[eta_ i j] = 1. -Proof. by rewrite cycTIisometry cfnorm_irr. Qed. - -Lemma cycTIiso_dirr i j : eta_ i j \in dirr G. -Proof. by rewrite dirrE cycTIiso_vchar /= cfnorm_cycTIiso. Qed. - -Lemma cycTIiso_orthonormal : orthonormal im_sigma. -Proof. by rewrite map_orthonormal ?irr_orthonormal. Qed. - -Lemma cycTIiso_eqE i1 i2 j1 j2 : - (eta_ i1 j1 == eta_ i2 j2) = ((i1 == i2) && (j1 == j2)). -Proof. -have /inj_in_eq-> := Zisometry_inj Isigma; try exact: irr_vchar. -by rewrite (inj_eq irr_inj) (inj_eq (dprod_Iirr_inj _)). -Qed. - -Lemma cycTIiso_neqN i1 i2 j1 j2 : (eta_ i1 j1 == - eta_ i2 j2) = false. -Proof. -rewrite -addr_eq0; apply/eqP=> /(congr1 (cfdot (eta_ i1 j1)))/eqP. -by rewrite cfdot0r cfdotDr !cfdot_cycTIiso !eqxx -mulrS pnatr_eq0. -Qed. - -Lemma cycTIiso1 : sigma 1 = 1. -Proof. by rewrite [sigma]unlock; case: cyclicTIiso_exists => ? []. Qed. - -Lemma cycTIiso_Ind : {in 'CF(W, V), forall phi, sigma phi = 'Ind[G, W] phi}. -Proof. by rewrite [sigma]unlock; case: cyclicTIiso_exists => ? []. Qed. - -Let sigma_Res_V : - [/\ forall phi, {in V, sigma phi =1 phi} - & forall psi : 'CF(G), orthogonal psi im_sigma -> {in V, psi =1 \0}]. -Proof. -have sigW i j : '[sigma 'chi_i, sigma 'chi_j] = (i == j)%:R. - by rewrite cycTIisometry cfdot_irr. -have [j | sigmaV sigma'V] := equiv_restrict_compl_ortho sWG nsVW cfWVbasis sigW. - rewrite /= -/cfWVbase -(eq_bigr _ (fun _ _ => linearZ _ _)) /= -linear_sum. - rewrite -cfun_sum_cfdot cycTIiso_Ind //. - by rewrite (basis_mem cfWVbasis) ?mem_nth ?size_image. -split=> [phi v Vv | psi /orthoPl o_psi_sigma]. - rewrite [phi]cfun_sum_cfdot linear_sum !sum_cfunE. - by apply: eq_bigr => k _; rewrite linearZ !cfunE sigmaV. -by apply: sigma'V => k; rewrite o_psi_sigma ?map_f ?mem_irr. -Qed. - -(* This is Peterfalvi, Theorem (3.2)(d). *) -Theorem cycTIiso_restrict phi : {in V, sigma phi =1 phi}. -Proof. by case: sigma_Res_V. Qed. - -(* This is Peterfalvi, Theorem (3.2)(e). *) -Theorem ortho_cycTIiso_vanish (psi : 'CF(G)) : - orthogonal psi im_sigma -> {in V, forall x, psi x = 0}. -Proof. by case: sigma_Res_V psi. Qed. - -(* This is PeterFalvi (3.7). *) -Lemma cycTIiso_cfdot_exchange (psi : 'CF(G)) i1 i2 j1 j2 : - {in V, forall x, psi x = 0} -> - '[psi, eta_ i1 j1] + '[psi, eta_ i2 j2] - = '[psi, eta_ i1 j2] + '[psi, eta_ i2 j1]. -Proof. -move=> psiV_0; pose phi : 'CF(W) := w_ i1 j1 + w_ i2 j2 - w_ i1 j2 - w_ i2 j1. -have Vphi: phi \in 'CF(W, V). - apply/cfun_onP=> g; rewrite inE negb_and negbK !inE orbC. - case/or3P=> [/cfun0-> // | W1g | W2g]; apply/eqP; rewrite !cfunE subr_eq0. - by rewrite addrC -[g]mulg1 /w_ !dprod_IirrE !cfDprodE ?lin_char1 ?addKr. - by rewrite -[g]mul1g /w_ !dprod_IirrE !cfDprodE ?lin_char1 ?addrK. -suffices: '[psi, 'Ind[G] phi] == 0. - rewrite -!cycTIiso_Ind // !linearB !linearD !cfdotBr !cfdotDr. - by rewrite -addrA -opprD subr_eq0 => /eqP. -rewrite (cfdotEr _ (cfInd_on sWG Vphi)) big1 ?mulr0 //. -by move=> _ /imset2P[x y Vx Gy ->]; rewrite cfunJ ?psiV_0 ?mul0r. -Qed. - -(* This is NC as defined in PeterFalvi (3.6). *) -Definition cyclicTI_NC phi := #|[set ij | '[phi, eta_ ij.1 ij.2] != 0]|. -Local Notation NC := cyclicTI_NC. - -Lemma cycTI_NC_opp (phi : 'CF(G)) : (NC (- phi)%R = NC phi)%N. -Proof. by apply: eq_card=> [[i j]]; rewrite !inE cfdotNl oppr_eq0. Qed. - -Lemma cycTI_NC_sign (phi : 'CF(G)) n : (NC ((-1) ^+ n *: phi)%R = NC phi)%N. -Proof. -elim: n=> [|n IH]; rewrite ?(expr0,scale1r) //. -by rewrite exprS -scalerA scaleN1r cycTI_NC_opp. -Qed. - -Lemma cycTI_NC_iso i j : NC (eta_ i j) = 1%N. -Proof. -rewrite -(cards1 (i, j)); apply: eq_card => [[i1 j1]]; rewrite !inE /=. -rewrite cfdot_cycTIiso //= pnatr_eq0 (can_eq oddb _ false) eqbF_neg negbK. -by rewrite -xpair_eqE eq_sym. -Qed. - -Lemma cycTI_NC_irr i : (NC 'chi_i <= 1)%N. -Proof. -apply: wlog_neg; rewrite -ltnNge => /ltnW/card_gt0P[[i1 j1]]. -rewrite inE cfdot_dirr ?(irr_dirr, cycTIiso_dirr) //=. -case: ('chi_i =P _) => [-> | _]; first by rewrite cycTI_NC_opp cycTI_NC_iso. -by case: ('chi_i =P _)=> [-> | _]; rewrite (cycTI_NC_iso, eqxx). -Qed. - -Lemma cycTI_NC_dirr f : f \in dirr G -> (NC f <= 1)%N. -Proof. by case/dirrP=> b [i ->]; rewrite cycTI_NC_sign cycTI_NC_irr. Qed. - -Lemma cycTI_NC_dchi di : (NC (dchi di) <= 1)%N. -Proof. by rewrite cycTI_NC_dirr ?dirr_dchi. Qed. - -Lemma cycTI_NC_0 : NC 0 = 0%N. -Proof. by apply: eq_card0 => ij; rewrite !inE cfdot0l eqxx. Qed. - -Lemma cycTI_NC_add n1 n2 phi1 phi2 : - (NC phi1 <= n1 -> NC phi2 <= n2 -> NC (phi1 + phi2)%R <= n1 + n2)%N. -Proof. -move=> ub1 ub2; apply: leq_trans {ub1 ub2}(leq_add ub1 ub2). -rewrite -cardsUI -[NC _]addn0 leq_add // subset_leq_card //. -apply/subsetP=> [[i j]]; rewrite !inE /= -negb_and cfdotDl. -by apply: contra => /andP[/eqP-> /eqP->]; rewrite addr0. -Qed. - -Lemma cycTI_NC_sub n1 n2 phi1 phi2 : - (NC phi1 <= n1 -> NC phi2 <= n2 -> NC (phi1 - phi2)%R <= n1 + n2)%N. -Proof. by move=> ub1 ub2; rewrite cycTI_NC_add ?cycTI_NC_opp. Qed. - -Lemma cycTI_NC_scale_nz a phi : a != 0 -> NC (a *: phi) = NC phi. -Proof. -move=> nz_a; apply: eq_card => ij. -by rewrite !inE cfdotZl mulf_eq0 negb_or nz_a. -Qed. - -Lemma cycTI_NC_scale a phi n : (NC phi <= n -> NC (a *: phi) <= n)%N. -Proof. -have [-> _ | /cycTI_NC_scale_nz-> //] := eqVneq a 0. -by rewrite scale0r cycTI_NC_0. -Qed. - -Lemma cycTI_NC_norm phi n : - phi \in 'Z[irr G] -> '[phi] <= n%:R -> (NC phi <= n)%N. -Proof. -move=> Zphi ub_phi; apply: leq_trans (_ : #|dirr_constt phi| <= n)%N. - rewrite {1}[phi]cfun_sum_dconstt // -sum1_card. - elim/big_rec2: _ => [|/= i n1 phi1 _]; first by rewrite cycTI_NC_0. - by apply: cycTI_NC_add; rewrite cycTI_NC_scale ?cycTI_NC_dchi. -rewrite -leC_nat (ler_trans _ ub_phi) ?cnorm_dconstt // -sumr_const. -apply: ler_sum => i phi_i; rewrite sqr_Cint_ge1 ?Cint_Cnat ?Cnat_dirr //. -by rewrite gtr_eqF -?dirr_consttE. -Qed. - -(* This is PeterFalvi (3.8). *) -Lemma small_cycTI_NC phi i0 j0 (a0 := '[phi, eta_ i0 j0]) : - {in V, forall x, phi x = 0} -> (NC phi < 2 * minn w1 w2)%N -> a0 != 0 -> - (forall i j, '[phi, eta_ i j] = (j == j0)%:R * a0) - \/ (forall i j, '[phi, eta_ i j] = (i == i0)%:R * a0). -Proof. -pose a i j := '[phi, eta_ i j]; pose A := [set ij | a ij.1 ij.2 != 0]. -rewrite -[NC phi]/#|A| ltnNge => phiV_0 ubA nz_a0. -have{phiV_0} Da i2 j2 i1 j1 : a i1 j1 = a i1 j2 + a i2 j1 - a i2 j2. - by rewrite cycTIiso_cfdot_exchange ?addrK. -have ubA2: ~~ (w2 + w1 <= #|A| + 2)%N. - rewrite addnC addn2 -ltnS (contra _ ubA) //; apply: (@leq_trans _ _.+3). - rewrite odd_geq /= ?odd_add ?oddW1 ?oddW2 // mul2n -addn_min_max -addnn. - by rewrite uphalf_double leq_add2l gtn_min !leq_max !ltnn orbF -neq_ltn. -(* This is step (3.8.1). *) -have Za i1 i2 j1 j2 : a i1 j2 == 0 -> a i2 j1 == 0 -> a i1 j1 == 0. - have [-> // | /negPf i2'1 /eqP Za12 /eqP Za21] := eqVneq i1 i2. - apply: contraR ubA2 => nz_a11. - pose L := [set (if a i1 j == 0 then i2 else i1, j) | j : Iirr W2]. - pose C := [set (i, if a i j1 == 0 then j2 else j1) | i : Iirr W1]. - have [<- <-]: #|L| = w2 /\ #|C| = w1 by rewrite !card_imset // => ? ? []. - have <-: #|[set (i1, j1); (i2, j2)]| = 2 by rewrite cards2 xpair_eqE i2'1. - rewrite -cardsUI leq_add ?subset_leq_card //; last first. - apply/subsetP=> _ /setIP[/imsetP[j _ ->] /imsetP[i _ []]]. - by case: ifP => _ <- ->; rewrite !inE ?Za21 ?(negPf nz_a11) !eqxx ?orbT. - apply/subsetP=> ij /setUP[] /imsetP[] => [j | i] _ {ij}->; rewrite inE. - by case: ifPn => // /eqP Za1j; rewrite (Da i1 j1) Za21 Za1j !add0r oppr_eq0. - by case: ifPn => // /eqP Zai1; rewrite (Da i1 j1) Za12 Zai1 !add0r oppr_eq0. -pose L i := [set ij | ij.1 == i] :&: A; pose C j := [set ij | ij.2 == j] :&: A. -have{ubA2} ubLC i j: (#|L i| + #|C j| != w2 + w1)%N. - apply: contraNneq ubA2 => <-; rewrite addnS leqW // -cardsUI -setIUl -setIIl. - rewrite -(card1 (i, j)) leq_add ?subset_leq_card ?subsetIr //. - by apply/subsetP=> ij /setIP[]; rewrite !inE. -have lbA L1 L2: L1 :&: L2 =i set0 -> (#|L1 :&: A| + #|L2 :&: A| <= #|A|)%N. - rewrite -cardsUI -setIUl -setIIl => /setP->. - by rewrite set0I cards0 addn0 subset_leq_card ?subsetIr. -have oL i1: ~~ [exists j, a i1 j == 0] -> #|L i1| = w2. - rewrite negb_exists => /forallP nz_a1. - transitivity #|predX (pred1 i1) (Iirr W2)|; last by rewrite cardX card1 mul1n. - by apply/eq_card=> ij; rewrite !inE andbT andb_idr // => /eqP->. -have oC i1 j1 j2 : a i1 j1 != 0 -> a i1 j2 == 0 -> #|C j1| = w1. - move=> nz_a11 /(Za i1)/contra/(_ nz_a11) nz_a1. - transitivity #|predX (Iirr W1) (pred1 j1)|; last by rewrite cardX card1 muln1. - by apply/eq_card=> ij; rewrite !inE andb_idr // => /eqP->. -(* This is step (3.8.2). *) -have [/existsP[j1 Za01] | /oL oL0] := boolP [exists j, a i0 j == 0]. - have j0'1 : j1 != j0 by apply: contraTneq Za01 => ->. - have oC0: #|C j0| = w1 by apply: oC nz_a0 Za01. - suffices Za0 i j: j != j0 -> a i j = 0. - left=> i j; rewrite -/(a i j) mulr_natl mulrb; have [->|/Za0//] := altP eqP. - by rewrite (Da i0 j1) !(Za0 _ j1) // subr0 add0r. - move=> j0'j; apply: contraNeq (ubLC i j0) => nz_aij; rewrite oC0 oL //. - apply: contra ubA => /existsP[_ /Za/contra/(_ nz_aij) nz_a_j]. - rewrite minn_mulr geq_min mul2n -addnn -{2}oC0 -(oC i0 j j1) ?lbA // => ij. - by rewrite !inE; apply/andP=> [[/eqP-> /idPn]]. -(* This is step (3.8.3). *) -suffices Za0 i j: i != i0 -> a i j = 0. - right=> i j; rewrite -/(a i j) mulr_natl mulrb; have [->|/Za0//] := altP eqP. - have /card_gt0P[i1 i0'i]: (0 < #|predC1 i0|)%N. - by rewrite cardC1 nirrW1 -(subnKC w1gt2). - by rewrite (Da i1 j0) !(Za0 i1) // subr0 addr0. -move=> i0'i; suffices /existsP[j1 Zai1]: [exists j, a i j == 0]. - by apply: contraNeq (ubLC i0 j) => /oC/(_ Zai1)->; rewrite oL0. -apply: contraR ubA; rewrite minn_mulr geq_min orbC mul2n -addnn => /oL{1}<-. -by rewrite -oL0 lbA // => ij; rewrite !inE; apply/andP=> [[/eqP-> /idPn]]. -Qed. - -(* A weaker version of PeterFalvi (3.8). *) -Lemma cycTI_NC_minn (phi : 'CF(G)) : - {in V, forall x, phi x = 0} -> (0 < NC phi < 2 * minn w1 w2)%N -> - (minn w1 w2 <= NC phi)%N. -Proof. -move=> phiV_0 /andP[/card_gt0P[[i0 j0]]]; rewrite inE /= => nz_a0 ubNC. -pose L := [seq (i0, j) | j : Iirr W2]; pose C := [seq (i, j0) | i : Iirr W1]. -have [oL oC]: #|L| = w2 /\ #|C| = w1 by rewrite !card_image // => i j []. -have [Da | Da] := small_cycTI_NC phiV_0 ubNC nz_a0. - rewrite geq_min -oC subset_leq_card //. - by apply/subsetP=> _ /codomP[i ->]; rewrite !inE /= Da eqxx mul1r. -rewrite geq_min orbC -oL subset_leq_card //. -by apply/subsetP=> _ /codomP[j ->]; rewrite !inE /= Da eqxx mul1r. -Qed. - -(* Another consequence of (3.8), used in (4.8), (10.5), (10.10) and (11.8). *) -Lemma eq_signed_sub_cTIiso phi e i j1 j2 : - let rho := (-1) ^+ e *: (eta_ i j1 - eta_ i j2) in - phi \in 'Z[irr G] -> '[phi] = 2%:R -> j1 != j2 -> - {in V, phi =1 rho} -> phi = rho. -Proof. -set rho := _ - _; move: phi => phi0 /= Zphi0 n2phi0 neq_j12 eq_phi_rho. -pose phi := (-1) ^+ e *: phi0; pose psi := phi - rho. -have{eq_phi_rho} psiV0 z: z \in V -> psi z = 0. - by move=> Vz; rewrite !cfunE eq_phi_rho // !cfunE signrMK subrr. -have{Zphi0} Zphi: phi \in 'Z[irr G] by rewrite rpredZsign. -have{n2phi0} n2phi: '[phi] = 2%:R by rewrite cfnorm_sign. -have Zrho: rho \in 'Z[irr G] by rewrite rpredB ?cycTIiso_vchar. -have n2rho: '[rho] = 2%:R. - by rewrite cfnormBd !cfdot_cycTIiso ?eqxx ?(negPf neq_j12) ?andbF. -have [oIphi _ Dphi] := dirr_small_norm Zphi n2phi isT. -have [oIrho _ Drho] := dirr_small_norm Zrho n2rho isT. -set Iphi := dirr_constt _ in oIphi Dphi. -set Irho := dirr_constt _ in oIrho Drho. -suffices /eqP eqIrho: Irho == Iphi by rewrite Drho eqIrho -Dphi signrZK. -have psi_phi'_lt0 di: di \in Irho :\: Iphi -> '[psi, dchi di] < 0. - case/setDP=> rho_di phi'di; rewrite cfdotBl subr_lt0. - move: rho_di; rewrite dirr_consttE; apply: ler_lt_trans. - rewrite real_lerNgt -?dirr_consttE ?real0 ?Creal_Cint //. - by rewrite Cint_cfdot_vchar ?dchi_vchar. -have NCpsi: (NC psi < 2 * minn w1 w2)%N. - suffices NCpsi4: (NC psi <= 2 + 2)%N. - by rewrite (leq_ltn_trans NCpsi4) // !addnn mul2n ltn_double leq_min w1gt2. - by rewrite cycTI_NC_sub // cycTI_NC_norm ?n2phi ?n2rho. -pose rhoId := dirr_dIirr (fun sk => (-1) ^+ (sk.1 : bool) *: eta_ i sk.2). -have rhoIdE s k: dchi (rhoId (s, k)) = (-1) ^+ s *: eta_ i k. - by apply: dirr_dIirrE => sk; rewrite rpredZsign cycTIiso_dirr. -rewrite eqEcard oIrho oIphi andbT -setD_eq0; apply/set0Pn=> [[dk1 phi'dk1]]. -have [[rho_dk1 _] psi_k1_lt0] := (setDP phi'dk1, psi_phi'_lt0 _ phi'dk1). -have dot_dk1: '[rho, dchi dk1] = 1. - rewrite Drho cfdot_suml (big_setD1 dk1) //= cfnorm_dchi big1 ?addr0 //. - move=> dk2 /setD1P[/negPf dk1'2 /dirr_constt_oppl]; rewrite cfdot_dchi dk1'2. - by case: eqP => [-> /negP[] | _ _]; rewrite ?subrr ?ndirrK. -have dot_dk2: 0 < '[rho, rho - dchi dk1]. - by rewrite cfdotBr dot_dk1 n2rho addrK ltr01. -have{dot_dk1 dot_dk2} [s [k Dk1 rho_k2]]: - exists s, exists2 k, rhoId (s, k.1) = dk1 & rhoId (~~ s, k.2) \in Irho. -- move/cfdot_add_dirr_eq1: dot_dk1. - rewrite dirr_dchi rpredN !cycTIiso_dirr //. - case=> // Dk1; [exists false, (j1, j2) | exists true, (j2, j1)]; - try apply: dirr_inj; rewrite ?dirr_consttE rhoIdE scaler_sign //=. - + by rewrite addrC Dk1 addKr in dot_dk2. - by rewrite Dk1 addrK in dot_dk2. -rewrite -Dk1 rhoIdE cfdotZr rmorph_sign in psi_k1_lt0. -have psi_k1_neq0: '[psi, eta_ i k.1] != 0. - by rewrite -(can_eq (signrMK s)) mulr0 ltr_eqF. -set dk2 := rhoId _ in rho_k2. -have NCk2'_le1 (dI : {set _}): - dk2 \in dI -> #|dI| = 2%N -> (NC (\sum_(dk in dI :\ dk2) dchi dk)%R <= 1)%N. -- rewrite (cardsD1 dk2) => -> /eqP/cards1P[dk ->]. - by rewrite big_set1 cycTI_NC_dirr ?dirr_dchi. -suffices /psi_phi'_lt0/ltr_geF/idP[]: dk2 \in Irho :\: Iphi. - rewrite rhoIdE cfdotZr signrN rmorphN mulNr oppr_ge0 rmorph_sign. - have := small_cycTI_NC psiV0 NCpsi psi_k1_neq0. - by case=> // ->; rewrite mulrCA nmulr_lle0 ?ler0n. -have: (1 + 1 < NC psi)%N. - apply (@leq_trans (minn w1 w2)); first by rewrite leq_min w1gt2. - apply: cycTI_NC_minn => //; rewrite NCpsi /NC. - by rewrite (cardsD1 (i, k.1)) inE /= psi_k1_neq0. -rewrite inE rho_k2 andbT ltnNge; apply: contra => phi_k2. -rewrite /psi Drho (big_setD1 dk2) //= Dphi (big_setD1 dk2) //=. -by rewrite addrAC opprD addNKr addrC cycTI_NC_sub ?NCk2'_le1. -Qed. - -(* This is PeterFalvi (3.9)(a). *) -Lemma eq_in_cycTIiso (i : Iirr W) (phi : 'CF(G)) : - phi \in dirr G -> {in V, phi =1 'chi_i} -> phi = sigma 'chi_i. -Proof. -move=> Dphi; rewrite -(inv_dprod_IirrK defW i). -case: (inv_dprod_Iirr _)=> /= i1 j1 EphiC. -pose psi : 'CF(G) := eta_ i1 j1 - phi. -have ZpsiV: {in V, forall g, psi g = 0}=> [g GiV|]. - by rewrite /psi !cfunE cycTIiso_restrict // -(EphiC _ GiV) subrr. -pose a i j := '[psi, eta_ i j]; pose S := [set ij | a ij.1 ij.2 != 0]. -case: (boolP ((i1, j1) \in S))=> [I1J1iS|]; last first. - rewrite inE negbK /a cfdotBl cfdot_cycTIiso !eqxx /=. - rewrite cfdot_dirr ?(irr_dirr, cycTIiso_dirr) //. - case: (boolP (phi == _))=> [|_]. - by rewrite opprK -(natrD _ 1 1) pnatr_eq0. - case: (boolP (phi == _))=> [/eqP //|]. - by rewrite subr0 oner_eq0. -have SPos : (0 < #|S|)%N by rewrite (cardD1 (i1,j1)) I1J1iS. -have SLt: (#|S| <= 2)%N. - by rewrite -[2]add1n cycTI_NC_sub // !cycTI_NC_dirr // cycTIiso_dirr. -have: (0 < #|S| < 2 * minn w1 w2)%N. - rewrite SPos; apply: leq_ltn_trans SLt _. - by rewrite -{1}[2%N]muln1 ltn_mul2l /= leq_min ![(1 < _)%N]ltnW. -move/(cycTI_NC_minn ZpsiV); rewrite leqNgt; case/negP. -by apply: leq_ltn_trans SLt _; rewrite leq_min w1gt2. -Qed. - -(* This is the second part of Peterfalvi (3.9)(a). *) -Lemma cfAut_cycTIiso u phi : cfAut u (sigma phi) = sigma (cfAut u phi). -Proof. -rewrite [phi]cfun_sum_cfdot !raddf_sum; apply: eq_bigr => ij _. -rewrite /= !(linearZ, cfAutZ) /= -aut_IirrE; congr (_ *: _) => {phi}. -apply: eq_in_cycTIiso => [|x Vx /=]. - by have /cycTIirrP[i [j ->]] := mem_irr ij; rewrite dirr_aut cycTIiso_dirr. -by rewrite cfunE cycTIiso_restrict // aut_IirrE cfunE. -Qed. - -Section AutCyclicTI. - -Variable iw : Iirr W. -Let w := 'chi_iw. -Let a := #[w]%CF. - -Let Zsigw : sigma w \in 'Z[irr G]. -Proof. by have [_ -> //] := cycTI_Zisometry; apply: irr_vchar. Qed. - -Let lin_w: w \is a linear_char := Wlin iw. - -(* This is Peterfalvi (3.9)(b). *) -Lemma cycTIiso_aut_exists k : - coprime k a -> - [/\ exists u, sigma (w ^+ k) = cfAut u (sigma w) - & forall x, coprime #[x] a -> sigma (w ^+ k) x = sigma w x]. -Proof. -case/(make_pi_cfAut G)=> u Du_a Du_a'. -suffices Dwk: sigma (w ^+ k) = cfAut u (sigma w). - by split=> [|x co_x_a]; [exists u | rewrite Dwk Du_a']. -rewrite cfAut_cycTIiso; congr (sigma _); apply/cfun_inP=> x Wx. -have Wxbar: coset _ x \in (W / cfker w)%G by rewrite mem_quotient. -rewrite exp_cfunE // cfunE -cfQuoEker //. -rewrite -lin_charX ?cfQuo_lin_char ?cfker_normal // -Du_a ?cfunE //. - by rewrite char_vchar ?cfQuo_char ?irr_char. -by rewrite [a]cforder_lin_char // dvdn_exponent. -Qed. - -(* This is Peterfalvi (3.9)(c). *) -Lemma Cint_cycTIiso_coprime x : coprime #[x] a -> sigma w x \in Cint. -Proof. -move=> co_x_a; apply: Cint_rat_Aint (Aint_vchar _ Zsigw). -have [Qb galQb [QbC AutQbC [w_b genQb memQb]]] := group_num_field_exists <[x]>. -have{memQb} [wx Dwx]: exists wx, sigma w x = QbC wx. - have /memQb Qbx := dvdnn #[x]. - have [sw1 /Qbx[wx1 Dwx1] [sw2 /Qbx[wx2 Dwx2] ->]] := vcharP _ Zsigw. - by exists (wx1 - wx2); rewrite rmorphB !cfunE Dwx1 Dwx2. -suffices: wx \in fixedField 'Gal({:Qb} / 1). - rewrite Dwx (galois_fixedField galQb) ?subvf // => /vlineP[z ->]. - by rewrite -in_algE fmorph_eq_rat fmorph_rat Crat_rat. -apply/fixedFieldP=> [|v_b _]; first exact: memvf. -have [v Dv] := AutQbC v_b; apply: (fmorph_inj QbC); rewrite Dv -Dwx. -have [u uQb uQb'] := dvd_restrict_cfAut (W / cfker w) #[x] v. -transitivity (sigma (cfAut u w) x); first by rewrite -cfAut_cycTIiso cfunE -uQb. -congr (sigma _ _); apply/cfun_inP=> y Wy; rewrite cfunE -cfQuoEker //. -rewrite uQb' ?char_vchar ?cfQuo_char ?irr_char // coprime_sym. -apply: coprime_dvdr co_x_a; rewrite [a]cforder_lin_char //. -by rewrite dvdn_exponent ?mem_quotient. -Qed. - -End AutCyclicTI. - -End Three. - -Arguments ortho_cycTIiso_vanish [gT G W W1 W2 defW] ctiW [psi]. - -Section ThreeSymmetry. - -Variables (gT : finGroupType) (G W W1 W2 : {group gT}). -Implicit Types (defW : W1 \x W2 = W) (xdefW : W2 \x W1 = W). -Local Notation sigma_ := (@cyclicTIiso gT G W _ _). -Local Notation w_ defW i j := (cyclicTIirr defW i j). - -Lemma cycTIisoC defW xdefW ctiW xctiW i j : - @sigma_ defW ctiW (w_ defW i j) = @sigma_ xdefW xctiW (w_ xdefW j i). -Proof. -apply: eq_in_cycTIiso; first exact: cycTIiso_dirr. -by rewrite /cyclicTIset setUC cyclicTIirrC; apply: cycTIiso_restrict. -Qed. - -Lemma cycTIiso_irrelC defW xdefW ctiW xctiW : - @sigma_ defW ctiW = @sigma_ xdefW xctiW. -Proof. -suffices: sigma_ ctiW =1 sigma_ xctiW by rewrite ![sigma_ _]unlock => /lfunP->. -move=> phi; have [z_ ->] := cfun_irr_sum phi; rewrite !linear_sum. -apply/eq_bigr=> ij _; have [i [j ->]] := cycTIirrP defW (mem_irr ij). -by rewrite !linearZ /= {1}cycTIisoC cyclicTIirrC. -Qed. - -Lemma cycTIiso_irrel defW defW' ctiW ctiW' : - @sigma_ defW ctiW = @sigma_ defW' ctiW'. -Proof. -have xdefW: W2 \x W1 = W by rewrite dprodC. -by rewrite !(cycTIiso_irrelC _ (cyclicTIhyp_sym ctiW xdefW)). -Qed. - -End ThreeSymmetry. |
