function isLS(llst) if #llst lt 2 then return false; end if; for line in llst do if #line lt 2 then return false; end if; end for; numpts := Maximum(&cat llst); for p in [1..numpts] do if Sort(&cat [Exclude(line,p) : line in llst | p in line]) ne Exclude([1..numpts],p) then return false; end if; end for; return true; end function; function PaddedDigits(n,b,m) seq := IntegerToSequence(n,b) cat [0 : i in [1..m]]; return [seq[i] : i in [1..m]]; end function; function Decode(line) bool,_,lst := Regexp("^([0-9]+)x([0-9]+)x([0-9]+):(.*)$",line); if not bool then bool,_,lst := Regexp(":.+ ([0-9]+)x([0-9]+)x([0-9]+):(.*)$",line); end if; error if not bool, "line not in correct format!\n"; pc := StringToInteger(lst[1]); lc := StringToInteger(lst[2]); clst := &cat[Reverse(PaddedDigits(StringToCode(a)-48,2,6)) : a in ElementToSequence(lst[4])]; j := #clst-pc*lc; for i := #clst-5 to #clst-j do clst[i] := clst[i+j]; end for; llst := []; for j in [1..lc] do lst := []; for i in [1..pc] do if clst[(i-1)*lc+j] eq 1 then Append(~lst,i); end if; end for; Append(~llst,lst); end for; assert isLS(llst); return pc, lc, llst; end function; function brac(M,lst) mat := Matrix(BaseRing(M),3,3,[]); for i in [1..3] do for j in [1..3] do mat[i,j] := M[i,lst[j]]; end for; end for; return Determinant(mat); end function; function CheckEmbed(llst,pnts) pc := #pnts; ans := true; for line in llst do p1 := line[1]; p2 := line[2]; linep := SequenceToSet(line) diff {p1,p2}; linep2 := {i : i in [1..pc] | not (i in {p1,p2}) and Determinant(Matrix(Parent(pnts[1][1]),3,3,[[pnts[i][1],pnts[i][2],pnts[i][3]],[pnts[p1][1],pnts[p1][2],pnts[p1][3]],[pnts[p2][1],pnts[p2][2],pnts[p2][3]]])) eq 0}; if linep ne linep2 then ans := false; end if; end for; return ans; end function; function Peq(pt1,pt2,gb) if pt1[1] eq 0 and pt2[1] eq 0 then return NormalForm(pt1[3]*pt2[2]-pt1[2]*pt2[3],gb) eq 0; else return NormalForm(pt2[1]*pt1[2]-pt1[1]*pt2[2],gb) eq 0 and NormalForm(pt2[1]*pt1[3]-pt1[1]*pt2[3],gb) eq 0; end if; end function; function BedIn0(llst,M,clst) eqs := []; noneqs := []; pc := Max(&cat llst); for p1 in [1..pc] do for p2 in [p1+1..pc] do p1p2 := [line : line in llst | p1 in line and p2 in line][1]; for p3 in [p2+1..pc] do b := brac(M,[p1,p2,p3]); if p3 in p1p2 then if b ne 0 then Append(~eqs,b); end if; else Append(~noneqs,b); end if; end for; end for; end for; I := ideal; // printf "%o variables, %o equations\n",Rank(BaseRing(M)),#eqs; ans := []; coords := [**]; for char in clst do if char eq 0 then F := Rationals(); else F := FiniteField(char); end if; I2 := ChangeRing(I, F); Groebner(I2); IId := ideal; if I2 eq IId then Append(~ans, false); Append(~coords,[]); else NR := Generic(I2); pnts := [[NormalForm(NR!M[i,j],I2) : i in [1..3]] : j in [1..NumberOfColumns(M)]]; sans := true; for i in [1..#pnts] do for j in [i+1..#pnts] do if Peq(pnts[i],pnts[j],I2) then sans := false; end if; end for; end for; sans := sans and not (0 in [NormalForm(NR!a,I2) : a in noneqs]); if sans then Append(~coords,[* pnts, I2 *]); else Append(~coords,[]); end if; Append(~ans,sans); end if; end for; return ans, coords; end function; // This looks for embeddings in F_2(t) function BedInF2t(llst,M) eqs := []; noneqs := []; pc := Max(&cat llst); for p1 in [1..pc] do for p2 in [p1+1..pc] do p1p2 := [line : line in llst | p1 in line and p2 in line][1]; for p3 in [p2+1..pc] do b := brac(M,[p1,p2,p3]); if p3 in p1p2 then if b ne 0 then Append(~eqs,b); end if; else Append(~noneqs,b); end if; end for; end for; end for; I := ideal; ans := []; coords := []; I2 := ChangeRing(I, GF(2)); Groebner(I2); IId := ideal; if I2 eq IId then Append(~ans, false); Append(~coords,[]); else NR := Generic(I2); pnts := [[NormalForm(NR!M[i,j],I2) : i in [1..3]] : j in [1..NumberOfColumns(M)]]; sans := true; for i in [1..#pnts] do for j in [i+1..#pnts] do if Peq(pnts[i],pnts[j],I2) then sans := false; end if; end for; end for; sans := sans and not (0 in [NormalForm(NR!a,I2) : a in noneqs]) and Dimension(I2) gt 0; if sans then Append(~coords,pnts); else Append(~coords,[]); end if; Append(~ans,sans); end if; return ans, coords; end function; function MakeMat(pc,lc,llst); // find 4 points such that it's complete quarilateral contains many points slst := [SequenceToSet(l) : l in llst]; _,pos := Max([#s : s in slst]); l1 := slst[pos]; slst0 := [l : l in slst | (l meet l1) ne {} and l ne l1]; _,pos := Max([#s : s in slst0]); l2 := slst0[pos]; p3 := SetToSequence(l1 meet l2)[1]; l2p := l2 diff {p3}; slst1 := [l : l in slst0 | (l meet l2p) ne {} and l ne l2]; _,pos := Max([#s : s in slst1]); l3 := slst1[pos]; p1 := SetToSequence(l2 meet l3)[1]; p2 := SetToSequence(l1 meet l3)[1]; lst := [i : i in [1..pc] | i notin l1 and i notin l2 and i notin l3]; set := SequenceToSet(lst); _,pos := Min([#(set diff &join[l : l in slst | p4 in l and (p1 in l or p2 in l or p3 in l)]) : p4 in lst]); p4 := lst[pos]; // now construct Sturmfels' matrix donelst := [p1,p2,p3,p4]; linep1p2 := [l : l in llst | p1 in l and p2 in l][1]; linep1p2 := [i : i in linep1p2 | not i in donelst]; donelst := donelst cat linep1p2; linep1p3 := [l : l in llst | p1 in l and p3 in l][1]; linep1p3 := [i : i in linep1p3 | not i in donelst]; donelst := donelst cat linep1p3; linep1p4 := [l : l in llst | p1 in l and p4 in l][1]; linep1p4 := [i : i in linep1p4 | not i in donelst]; donelst := donelst cat linep1p4; linep2p3 := [l : l in llst | p2 in l and p3 in l][1]; linep2p3 := [i : i in linep2p3 | not i in donelst]; donelst := donelst cat linep2p3; linep2p4 := [l : l in llst | p2 in l and p4 in l][1]; linep2p4 := [i : i in linep2p4 | not i in donelst]; donelst := donelst cat linep2p4; linep3p4 := [l : l in llst | p3 in l and p4 in l][1]; linep3p4 := [i : i in linep3p4 | not i in donelst]; donelst := donelst cat linep3p4; cnt := #linep1p2 + #linep1p3 + #linep1p4 + #linep2p3 + #linep2p4 + #linep3p4; cnt := cnt + 2*(pc-#donelst); P := PolynomialRing(Integers(),cnt); mat := Matrix(P,3,pc,[]); mat[1,p1] := 0; mat[2,p1] := 1; mat[3,p1] := 0; mat[1,p2] := 0; mat[2,p2] := 0; mat[3,p2] := 1; mat[1,p3] := 1; mat[2,p3] := 0; mat[3,p3] := 0; mat[1,p4] := 1; mat[2,p4] := 1; mat[3,p4] := 1; cnt := 1; for i in linep1p2 do mat[1,i] := 0; mat[2,i] := 1; mat[3,i] := P.cnt; cnt +:= 1; end for; for i in linep1p3 do mat[3,i] := 0; mat[1,i] := 1; mat[2,i] := P.cnt; cnt +:= 1; end for; for i in linep1p4 do mat[1,i] := 1; mat[3,i] := 1; mat[2,i] := P.cnt; cnt +:= 1; end for; for i in linep2p3 do mat[1,i] := 1; mat[2,i] := 0; mat[3,i] := P.cnt; cnt +:= 1; end for; for i in linep2p4 do mat[1,i] := 1; mat[2,i] := 1; mat[3,i] := P.cnt; cnt +:= 1; end for; for i in linep3p4 do mat[2,i] := 1; mat[3,i] := 1; mat[1,i] := P.cnt; cnt +:= 1; end for; for i in [i : i in [1..pc] | not i in donelst] do mat[2,i] := 1; mat[3,i] := P.cnt; cnt +:= 1; mat[1,i] := P.cnt; cnt +:= 1; end for; return mat; end function; function BedIn(llst,clst) pc := Max(&cat llst); return BedIn0(llst,MakeMat(pc,#llst,llst),clst); end function; function lineab(a,b,llst) return [l : l in llst | (a in l) and (b in l)][1]; end function; function MakeI(llst); // For every pair of points a,b, find two lines through them that // intersect in a third point, the longest such triple becomes 0a, 0b, // ab. Let (1,0) be the point on 0b such that the length of (1,0)a is // maximized. Let (0,1) be the point on 0a such that the length of (0,1)b // is maximized. Count points not on any of these lines. Find a,b that // minimizes this count. lc := #llst; pc := Max(&cat llst); bmax := 0; slst := [SequenceToSet(l) : l in llst]; for a in [1..pc] do for b in [a+1..pc] do max := 0; abline := lineab(a,b,llst); for o in [1..pc] do if (not o in abline) and #lineab(o,a,llst) + #lineab(o,b,llst) gt max then max := #lineab(o,a,llst) + #lineab(o,b,llst); maxo := o; end if; end for; line0ap := SetToSequence(lineab(maxo,a,slst) diff {maxo,a}); line0bp := SetToSequence(lineab(maxo,b,slst) diff {maxo,b}); if (line0ap ne []) and (line0bp ne []) then _,ind := Max([#lineab(c,b,llst) : c in line0ap]); aa := line0ap[ind]; _,ind := Max([#lineab(c,a,llst) : c in line0bp]); bb := line0bp[ind]; dum := #(lineab(a,b,slst) join lineab(a,maxo,slst) join lineab(maxo,b,slst) join lineab(aa,b,slst) join lineab(a,bb,slst)) + #(lineab(aa,b,slst) meet lineab(a,bb,slst))/2; if dum gt bmax then bmax := dum; inf1 := a; inf2 := b; oo := maxo; a1 := aa; a2 := bb; end if; end if; end for; end for; infline := lineab(inf1,inf2,slst); line10 := lineab(oo,inf1,slst); line20 := lineab(oo,inf2,slst); line11 := lineab(a2,inf1,slst); line21 := lineab(a1,inf2,slst); K := FreeAlgebra(RationalField(),50); mat := [[K!0,K!0,K!0] : i in [1..pc]]; mat[oo] := [1,0,0]; mat[inf1] := [0,1,0]; mat[inf2] := [0,0,1]; mat[a1] := [1,1,0]; mat[a2] := [1,0,1]; cnt := 0; for i in line10 diff {oo,a1,inf1} do cnt +:= 1; mat[i] := [1,K.cnt,0]; end for; for i in line11 diff {a2,inf1} do mat[i] := [1,0,1]; ll := line10 meet lineab(i,inf2,slst); if #ll eq 1 then mat[i][2] := mat[Random(ll)][2]; else cnt +:= 1; mat[i][2] := K.cnt; end if; end for; for i in line20 diff {oo,a2,inf2} do cnt +:= 1; mat[i] := [1,0,K.cnt]; end for; for i in line21 diff {a1,inf2} do mat[i] := [1,1,0]; ll := line20 meet lineab(i,inf1,slst); if #ll eq 1 then mat[i][3] := mat[Random(ll)][3]; else cnt +:= 1; mat[i][3] := K.cnt; end if; end for; for i in infline diff {inf1,inf2} do cnt +:= 1; mat[i] := [0,1,K.cnt]; end for; badlst := {1..pc} diff (infline join line10 join line11 join line20 join line21); for i in badlst do mat[i] := [1,0,0]; ll := (line20 join line21) meet lineab(i,inf1,slst); if #ll ge 1 then mat[i][3] := mat[Random(ll)][3]; else cnt +:= 1; mat[i][3] := K.cnt; end if; ll := (line10 join line11) meet lineab(i,inf2,slst); if #ll ge 1 then mat[i][2] := mat[Random(ll)][2]; else cnt +:= 1; mat[i][2] := K.cnt; end if; end for; // start writing down equations eqs := []; noneqs := [mat[i][3] : i in [1..pc] | not (i in line10 join infline)] cat [mat[i][3]-1 : i in [1..pc] | not (i in line11 join infline)] cat [mat[i][2] : i in [1..pc] | not (i in line20 join infline)] cat [mat[i][2]-1 : i in [1..pc] | not (i in line21 join infline)]; slst2 := SequenceToSet(slst) diff {infline,line10,line11,line20,line21}; for line in slst2 do if inf2 in line then linep := line diff {inf2}; pt2 := SetToSequence(linep)[1]; linep := linep diff {pt2}; dum := mat[pt2][2]; for i in {1..pc} diff ({pt2} join infline) do if i in linep then Append(~eqs,dum-mat[i][2]); else Append(~noneqs,dum-mat[i][2]); end if; end for; else if inf1 in line then linep := line diff {inf1}; pt2 := SetToSequence(linep)[1]; linep := linep diff {pt2}; dum := mat[pt2][3]; for i in {1..pc} diff (infline join {pt2}) do if i in linep then Append(~eqs,dum-mat[i][3]); else Append(~noneqs,dum-mat[i][3]); end if; end for; else if #(line meet infline) gt 0 then // [0,1,e] = [1,a,b]*t + [1,c,d]*s implies // b-d = e*(a-c) infpt := Random(line meet infline); linep := line diff {infpt}; e := mat[infpt][3]; glst := SetToSequence(line meet {oo}) cat SetToSequence(line meet line20) cat SetToSequence(line meet line21) cat SetToSequence(line meet line10) cat SetToSequence(line meet line11); if #glst gt 0 then pt2 := glst[1]; else pt2 := SetToSequence(linep)[1]; end if; linep := linep diff {pt2}; a := mat[pt2][2]; b := mat[pt2][3]; for i in {1..pc} diff (infline join {pt2}) do if i in linep then Append(~eqs,b-mat[i][3] - e*(a-mat[i][2])); else Append(~noneqs,b-mat[i][3] - e*(a-mat[i][2])); end if; end for; else // no infinite point on line // (a,b), (c,d) and (e,f) colinear iff // a-e = (c-e)*(d-f)^-1*(b-f) // if first point at infinity (0,a,b) then // a = (c-e)*(d-f)^-1*b // try to simplify (d-f) glst2 := SetToSequence(line meet line20) cat SetToSequence(line meet line21); glst1 := SetToSequence(line meet line10) cat SetToSequence(line meet line11); if #glst1 ge 2 or #glst2 ge 2 then if #glst1 ge 2 then ptcd := glst1[1]; ptef := glst1[2]; linep := line diff {ptcd,ptef}; for i in {1..pc} diff {ptcd,ptef} do if i in linep then Append(~eqs,mat[i][2]-mat[ptef][2] - ((mat[ptcd][2]-mat[ptef][2])* (mat[ptcd][3]-mat[ptef][3])* (mat[i][3]-mat[ptef][3]))); else if i in infline then Append(~noneqs,mat[i][2] - ((mat[ptcd][2]-mat[ptef][2])* (mat[ptcd][3]-mat[ptef][3])* mat[i][3])); else Append(~noneqs,mat[i][2]-mat[ptef][2] - ((mat[ptcd][2]-mat[ptef][2])* (mat[ptcd][3]-mat[ptef][3])* (mat[i][3]-mat[ptef][3]))); end if; end if; end for; else ptdc := glst2[1]; ptfe := glst2[2]; linep := line diff {ptdc,ptfe}; for i in {1..pc} diff {ptdc,ptfe} do if i in linep then Append(~eqs,mat[i][3]-mat[ptfe][3] - ((mat[ptdc][3]-mat[ptfe][3])* (mat[ptdc][2]-mat[ptfe][2])* (mat[i][2]-mat[ptfe][2]))); else if i in infline then Append(~noneqs,mat[i][3] - ((mat[ptdc][3]-mat[ptfe][3])* (mat[ptdc][2]-mat[ptfe][2])* mat[i][2])); else Append(~noneqs,mat[i][3]-mat[ptfe][3] - ((mat[ptdc][3]-mat[ptfe][3])* (mat[ptdc][2]-mat[ptfe][2])* (mat[i][2]-mat[ptfe][2]))); end if; end if; end for; end if; else // we will need an extra variable if #(line meet line20) gt 0 then pt1 := Random(line meet line20); const := 2; elif #(line meet line10) gt 0 then pt1 := Random(line meet line10); const := 3; elif #(line meet line21) gt 0 then pt1 := Random(line meet line21); const := 2; elif #(line meet line11) gt 0 then pt1 := Random(line meet line11); const := 3; else pt1 := SetToSequence(line)[1]; const := 3; end if; linep := line diff {pt1}; pt2 := SetToSequence(linep)[1]; linep := linep diff {pt2}; if const eq 2 then d := mat[pt1][2]; c := mat[pt1][3]; f := mat[pt2][2]; e := mat[pt2][3]; else d := mat[pt1][3]; c := mat[pt1][2]; f := mat[pt2][3]; e := mat[pt2][2]; end if; cnt +:= 1; Append(~eqs,(d-f)*K.cnt-1); Append(~eqs,K.cnt*(d-f)-1); for i in {1..pc} diff {pt1,pt2} do if i in linep then if const eq 2 then Append(~eqs,mat[i][3]-e - ((c-e)*K.cnt*(mat[i][2]-f))); else Append(~eqs,mat[i][2]-e - ((c-e)*K.cnt*(mat[i][3]-f))); end if; else if const eq 2 then if i in infline then Append(~noneqs,mat[i][3] - ((c-e)*K.cnt*mat[i][2])); else Append(~noneqs,mat[i][3]-e - ((c-e)*K.cnt*(mat[i][2]-f))); end if; else if i in infline then Append(~noneqs,mat[i][2] - ((c-e)*K.cnt*mat[i][3])); else Append(~noneqs,mat[i][2]-e - ((c-e)*K.cnt*(mat[i][3]-f))); end if; end if; end if; end for; end if; end if; end if; end if; end for; K2 := FreeAlgebra(Rationals(),cnt); map := [K2.i : i in [1..cnt]] cat [1 : i in [cnt+1..50]]; smap := hom K2 | map>; mat2 := [[smap(lst[1]),smap(lst[2]),smap(lst[3])] : lst in mat]; eqs2 := [smap(e) : e in eqs]; noneqs2 := [smap(e) : e in noneqs]; I := ideal; return mat2,I,noneqs2; end function; function NonComBedIn(llst,clst) M, I, noneqs := MakeI(llst); ans := []; gbs := []; for c in clst do if c eq 0 then I2 := ChangeRing(I,Rationals()); else I2 := ChangeRing(I,GF(c)); end if; if GroebnerBasis(I2) eq [1] then Append(~ans,false); else NR := Generic(I2); pcnt := #{[NormalForm(NR!M[j,i],I2) : i in [1..3]] : j in [1..#M]}; Append(~ans,(pcnt eq #M) and not (0 in [NormalForm(NR!a,I2) : a in noneqs])); end if; Append(~gbs,I2); end for; return ans, gbs; end function; function PrintPnts(pnts) for i in [1..#pnts] do printf "%o = [%o,%o,%o]\n",i,pnts[i][1],pnts[i][2],pnts[i][3]; end for; return true; end function; function PrintPntsTeXTable(pnts,R) printf "\\begin{tabular}{|c||"; for i in [1..#pnts] do printf "c|"; end for; printf "}\n\\hline "; for i in [1..R] do printf " & $R_{%o}$",i; end for; for i in [1..(#pnts-R)] do printf " & $G_{%o}$",i; end for; printf " \\\\\n \\hline x "; for i in [1..#pnts] do printf " & %o",pnts[i][1]; end for; printf " \\\\\n y "; for i in [1..#pnts] do printf " & %o",pnts[i][2]; end for; printf " \\\\\n z "; for i in [1..#pnts] do printf " & %o",pnts[i][3]; end for; printf " \\\\\n"; return true; end function; function DoFile(filename,clst,from_line,to_line); fh := Open(filename,"r"); line := Gets(fh); cnt := 0; cnts := [0 : i in [1..#clst]]; Ncnts := [0 : i in [1..#clst]]; ans := false; while not IsEof(line) do cnt +:= 1; if cnt ge from_line and cnt le to_line then pc, lc, llst := Decode(line); bool,coords := BedIn0(llst,MakeMat(pc,lc,llst),clst); clst2 := []; for j in [1..#clst] do if bool[j] then printf "space %o embeds in charactaristic %o\n",cnt,clst[j]; printf "whith coordinates:\n"; PrintPnts(coords[j][1]); cnts[j] +:= 1; else Append(~clst2,clst[j]); end if; end for; bool, gbs := NonComBedIn(llst,clst2); for j in [1..#clst2] do if bool[j] then printf "space %o possibly embeds NON-COMMUTATIVELY in charactaristic %o\n",cnt,clst2[j]; Ncnts[Index(clst,clst2[j])] +:= 1; end if; end for; if cnt mod 1000 eq 0 then printf "now at line %o\n",cnt; end if; end if; line := Gets(fh); end while; return cnts,Ncnts; end function; function DoFileF2t(filename); fh := Open(filename,"r"); line := Gets(fh); cnt := 0; cnts := [0]; while not IsEof(line) do pc, lc, llst := Decode(line); bool,coords := BedInF2t(llst,MakeMat(pc,lc,llst)); cnt +:= 1; if bool[1] then printf "space %o embeds in P(F_2(t))^2\n",cnt; printf "whith coordinates:\n"; PrintPnts(coords[1]); cnts[1] +:= 1; end if; line := Gets(fh); end while; return cnts; end function; function FileToLst(filename) ans := []; fh := Open(filename,"r"); line := Gets(fh); while not IsEof(line) do pc, lc, llst := Decode(line); Append(~ans,llst); line := Gets(fh); end while; return ans; end function;