/*
%%%%%%%%%%
%%%%%%%%%%
%%%%%%%%%%
MAGMA code for collineations of E_7(2)

This file contains the following:

(1) Setup of the group E_7(2) in the Groups of Lie type package.

(2) Code accompanying Theorem 4.7 in "Opposition diagrams for automorphisms of small spherical buildings" (J. Parkinson, H. Van Maldeghem)

%%%%%%%%%%
%%%%%%%%%%
%%%%%%%%%%
*/



/*
%%%%%%%%%%%
(1) Setting up the group E6(2)
%%%%%%%%%%%
*/


X:="E7";
q:=2;
F<e>:=GF(q);
RD:=RootDatum(X  : Isogeny:="SC");
G:=GroupOfLieType(RD,F);

//The Coxeter group W:
WCox<[t]>:=WeylGroup(GrpFPCox,G);//as a finitely presented abstract group
ww0:=LongestElement(WCox);//the longest element
WPerm,f:=CoxeterGroup(GrpPermCox,WCox);//a copy of W as a permutation group
invf:=Inverse(f);//converting between WPerm and WCox

//The Chevalley generators:
x:=function(i,k);
	return
	elt<G|<i,k>>;
end function;

//The elements s(i)=n_i(1): 
s:=function(i);
	return
	elt<G|i>;
end function;

//auxiliary code for converting between elements of W and elements of N:
CoxToG:=function(w);
	ww:=Id(G);
	for k in {1..Length(w)} do;
		ww:=ww*s(Eltseq(w)[k]);
	end for;
	return
	ww;
end function;
GToCox:=function(w);
	s:=Eltlist(w);
	ww:=Id(WCox);
	for k in {1..#s} do;
		ww:=ww*t[s[k]];
	end for;
	return
	ww;
end function;
SeqToG:=function(w);//gives the element of G from the sequence of Coxeter group element w
	temp:=Id(G);
	for i in {1..#w} do;
		temp:=temp*s(w[i]);
	end for;
	return
	temp;
end function;


	
w0:=CoxToG(ww0);//the longest element, considered as an element of N

//Computing the W-valued distance function in the building:
delta:=function(g1,g2);
	if g1 in G and g2 in G then;
		u,h,w,b:=Bruhat(g1^(-1)*g2);
		return
		w;
	end if;
end function;

/*
The following command chooses k chambers hB at random, and computes w=delta(hB,ghB). If w=w0 then 1 is returned. If w\neq w0 for all k chambers then 0 is returned.
*/

chamberop:=function(k,g);
	tt:={};
	for n in {1..k} do;
		gg:=Random(G : Uniform:=true);
		if delta(gg,g*gg) eq w0 then;
			tt:=tt join {gg};
			break n;
		end if;
	end for;
	return
	#tt;
end function;


one:=[* *];
for j in {1..Rank(RD)} do;
	one:=Append(one,1);
end for;
//finds vertices of each type mapped to opposite
vertexstructure:=function(nn,g);//the first variable gives accuracy
	sequence:=[* *];
	for j in {1..Rank(RD)} do;
		sequence:=Append(sequence,0);
	end for;
	for n in {1..nn} do;
		gg:=Random(G : Uniform:=true);
		w:=GToCox(delta(Id(G),w0*delta(gg,g*gg)));
		s:=Eltseq(w);
		ss:={s[j] : j in {1..#s}};
		for i in {1..Rank(RD)} do;
		if i notin ss then;
			sequence[i]:=1;
		end if;
		end for;
		if sequence eq one then;
			break n;
		end if;	
	end for;
	return
	sequence;
end function;

//finds simplex of given type to opposite:
simplexop:=function(nn,type,g);
	sequence:=0;
	for n in {1..nn} do;
		gg:=Random(G : Uniform:=true);
		w:=GToCox(delta(Id(G),w0*delta(gg,g*gg)));
		s:=Eltseq(w);
		ss:={s[j] : j in {1..#s}};
			if ss subset {k : k in {1..Rank(RD)} | k notin type} then;
				sequence:=1;
				break n;
			end if;
	end for;
	return
	sequence;
end function;




//Some root system routines:
root:=function(i);//root(i) gives the i-th root in the standard MAGMA ordering.
	return
	Roots(RD: Basis:="Root")[i];
end function;
//the standard order for MAGMA writing elements of the unipotent U:
standardorder:=[ 7, 13, 19, 25, 31, 30, 36, 41, 45, 49, 34, 39, 44, 48, 52, 47, 51, 55, 54, 57,
56, 58, 59, 60, 61, 62, 63, 6, 12, 18, 24, 27, 23, 29, 33, 35, 38, 40, 43, 42, 
46, 50, 53, 5, 11, 16, 17, 22, 21, 26, 28, 32, 37, 4, 10, 9, 15, 14, 20, 3, 8, 
2, 1 ];
//computing inversion set (enter w as element of WPerm):
inversionset:=function(w);//MAGMA uses right action
	return
	{@i : i in standardorder | Index(Roots(RD:Basis:="Root"),Image(w,RootGSet(WPerm),Root(WPerm,i))) in {NumPosRoots(RD)+1..2*NumPosRoots(RD)}@};
end function;



/*
%%%%%%%%%%%
(2) Code for Theorem 4.7
%%%%%%%%%%%
*/

//the analysis theta2.
theta2:=x(44,1)*x(45,1)*x(46,1);	
//routine to determine if a root dominates another
dominates:=function(r1,r2);
	r:=root(r1)-root(r2);
	counter:=0;
	rr:=Eltseq(r);
	for i in {1..#rr} do;
		if rr[i] ge 0 then;
			counter:=counter+1;
		end if;
	end for;
	if counter eq #rr then;
		return
		1;
	end if;
	if counter lt #rr then;
		return 
		0;
	end if;
end function;
//code to order a set into MAGMA's standard order for U (this makes some computation quicker)
orderset:=function(ss);
	temp:={@ @};
	for i in {1..#standardorder} do;
		if standardorder[i] in ss then;
			temp:=temp join {standardorder[i]};
		end if;
	end for;
return
temp;
end function;

uset2:=orderset({i : i in {1..63} | dominates(i,44) eq 1} join {i : i in {1..63} | dominates(i,45) eq 1} join {i : i in {1..63} | dominates(i,46) eq 1});

uu2:=function(z);//with z a 17-tuple (automatically puts "1" in the 44,45,46 root subgroups)
	seq:=[];
	counter:=1;
	for ii in {1..#uset2} do;
		i:=uset2[ii];
		if i notin {44,45,46} then;
			seq:=Append(seq,<uset2[ii],z[counter]>);
			counter:=counter+1;
		end if;
		if i in {44,45,46} then;
			seq:=Append(seq,<uset2[ii],1>);
		end if;
	end for;
	return
	elt<G|seq>;
end function;

//The following code searches the 2^17 elements (moderately long run, with count-down)
wvalues2:={};
search:=CartesianPower(F,17);
counter:=2^(17);
for z in search do;
	counter:=counter-1;
	if counter/1000 in Integers() then;
		counter;
	end if;
	wvalues2:=wvalues2 join {delta(Id(G),w0^(-1)*uu2(z)*w0)};
end for;
Max({Length(GToCox(w)) : w in wvalues2});//hence theta2 is domestic.

//to find vertices of each type mapped to opposite, run the code:
vertexstructure(100000,theta2);




//the analysis theta1.
theta1:=x(44,1)*x(46,1);	
//read in the dominates and ordered set code from above.

uset1:=orderset({i : i in {1..63} | dominates(i,44) eq 1} join {i : i in {1..63} | dominates(i,46) eq 1});

uu1:=function(z);//with z a 16-tuple (automatically puts "1" in the 44,46 root subgroups)
	seq:=[];
	counter:=1;
	for ii in {1..#uset1} do;
		i:=uset1[ii];
		if i notin {44,46} then;
			seq:=Append(seq,<uset1[ii],z[counter]>);
			counter:=counter+1;
		end if;
		if i in {44,46} then;
			seq:=Append(seq,<uset1[ii],1>);
		end if;
	end for;
	return
	elt<G|seq>;
end function;

//The following code searches the 2^16 elements (moderately long run, with count-down)
wvalues1:={};
search:=CartesianPower(F,16);
counter:=2^(16);
for z in search do;
	counter:=counter-1;
	if counter/1000 in Integers() then;
		counter;
	end if;
	wvalues1:=wvalues1 join {delta(Id(G),w0^(-1)*uu1(z)*w0)};
end for;
Max({Length(GToCox(w)) : w in wvalues1});//hence theta1 is domestic.

//to find vertices of each type 1,3,4,6, run the code:
simplexop(10000,{1},theta1);
simplexop(10000,{3},theta1);
simplexop(10000,{4},theta1);
simplexop(10000,{6},theta1);


/*
We now show that there are no type {1,3} simplices mapped onto opposite. It turns out that there are 1141419 cases to  consider (and this is manageable in a day-night run).
*/
jj:={2,4,5,6,7};
repsw:={@ f(w^(-1)) : w in Transversal(WCox,jj)@};//representatives for the type {1,3}-simplices in apartment (as elements of WPerm)
noncommuting:={@ 7, 13, 25, 30, 41, 44, 12, 24, 29, 40, 46, 5, 17, 22, 4, 9, 3 @};//the root indices that do not commute with theta4
wvalues:={};
counter:=1141419;
for w in repsw do;
	invset:=inversionset(w);
	invset2:={@ @};//here we construct the (ordered) intersection of the inversion set of w with the noncommuting set
	for i in {1..#invset} do;
		if invset[i] in noncommuting then;
			invset2:=invset2 join {invset[i]};
		end if;
	end for;
	ww:=CoxToG(invf(w));
	for z in CartesianPower(F,#invset2) do;
		counter:=counter-1;
		if counter/1000 in Integers() then;
			counter;
		end if;
		seq:=[];
		for j in {1..#invset2} do;
			seq:=Append(seq,<invset2[j],z[j]>);
		end for;
		g:=elt<G|seq>*ww;//here is the representative of G/P
		wvalues:=wvalues join {delta(g,theta1*g)};
	end for;
end for;

//then we check that none of the delta-values (stored in wvalues) lie in w_0W_{2,4,5,6,7}:
{f(ww0^(-1)*GToCox(w)) : w in wvalues} meet {w : w in StandardParabolicSubgroup(WPerm,{2,4,5,6,7})};







