################################################################## ################################################################## ################################################################## #### #### #### GAP-Program #### #### `BISTELLAR_EQUIVALENT' #### #### #### #### Version 02/99 #### #### by Frank Lutz, TU Berlin, Germany #### #### #### #### based on the #### #### #### #### GAP-Program #### #### `BISTELLAR' #### #### #### #### Second Version 02/99 #### #### by Frank Lutz, TU Berlin, Germany #### #### #### #### First Version 11/97 #### #### by Anders Björner, KTH Stockholm, Sweden, #### #### Frank Lutz, TU Berlin, Germany #### #### #### ################################################################## ################################################################## ################################################################## # The program BISTELLAR_EQUIVALENT provides # # 1. a heuristic (!!) to examine whether a test simplicial manifold # is bistellarly equivalent to a reference triangulation of a manifold # of which we know its homeomorphism type; thus the program can be used # used to determine the homeomorphism type of a simplicial manifold; # # 2. a test to find out if two simplicial manifolds (two strongly # connected simplicial pseudomanifolds) are combinatorially # isomorphic or not. # # The program is based on a simulated-annealing type random strategy # to perform bistellar moves which modify the triangulation # of a manifold locally but do not change the PL-homeomorphism type. # How to use the program? # # The program BISTELLAR_EQUIVALENT can be easily adapted to deal with # individual test objects. All settings, which can or needed # to be altered or added for this end, are marked with an arrow <--- ! # # (A) Before running BISTELLAR_EQUIVALENT, use the program BISTELLAR # to obtain a small or minimal triangulation of the reference manifold # and then include the facets of the test and the reference manifold # at the marked places within the functions `Test_Object' # and `Reference_Object'. # # (B) In the `Main Part', which you find at the end # of this listing, a number of variables can be set: # # log2file - write output to a log file; # RandomSeed(i) - different but fixed random sequences are # used for destinct integers `i', allowing # you to reproduce any `random result'; # rounds - maximal number of moves that are # performed. # # (C) Bistellar flip strategy: # # There is a priory no optimal flip strategy for every pair # of a test and a reference object. Thus, for any such pair # you might have to adapt the strategy and, in particular, # the values of the parameters `heating' and `relaxation'. # For dimensions 2, 3, and 4, we have included strategies # that work well in many cases. # # How to call the program? # # (D) Install GAP 3 on your computer. Adapt the program BISTELLAR_EQUIVALENT # as specified in (A) - (C) and save it as a file, start GAP, # and call BISTELLAR_EQUIVALENT by the command # # gap> Read("BISTELLAR_EQUIVALENT"); # # (E) The program stops as soon as it has processed # all rounds, if no further options for flips # are available (no_options_flag=1), # or if the program concluded that the test object # is bistellarly equivalent or combinatorially isomorphic # to the reference object (flag_equivalent=1). # # (F) The main (global) variables that carry the information # about the present complex in every round are: # # faces[max] - maximal faces; # faces[i] - (i-1)-dimensional faces; # F - essentially the f-vector, f_i = F_(i+1); # g - g-vector. # # (G) gap> quit; # Exercise to get acquainted with the program: # # Call BISTELLAR_EQUIVALENT with the given settings. # The program will then perform a number of flips # until it will conclude that the test example, # a 15-vertex triangulation of the 3-dimensional # Klein bottle, is bistellarly equivalent to the # reference example, the unique minimal triangulation # of the 3-dimensional Klein bottle with 9 vertices. # Now use different random sequences and rerun! # References: # # A. Björner, F.H. Lutz. # Simplicial manifolds, bistellar flips # and a 16-vertex triangulation of the # Poincaré homology 3-sphere. # Exp. Math. 9, 275-289 (2000). # # F.H. Lutz. # Triangulated Manifolds with Few Vertices and # Vertex-Transitive Group Actions. # Dissertation. Shaker Verlag, Aachen, 1999. # # M. Schönert et.al. # GAP -- Groups, Algorithms, and Programming. # Lehrstuhl D für Mathematik, Rheinisch Westfälische # Technische Hochschule, Aachen, Germany, fifth edition, 1995, # http://www.math.rwth-aachen.de/LDFM/homes/GAP/WWW/ ################################################################## ################################################################## ### Defining variables and functions ### ################################################################## ################################################################## ### Global variables and functions ### facets:=[]; dim:=0; max:=0; faces_A:=[]; maxvertex:=0; F_A:=[]; h:=[]; g:=[]; det_A:=0; faces_B:=[]; F_B:=[]; det_B:=0; flag_equivalent:=0; rounds:=0; chi:=0; sum:=0; raw_options:=[]; options:=[]; no_options_flag:=0; randomelement:=[]; log2file:=0; file:=String("BISTELLAR_EQUIVALENT.doc"); ball_boundary_faces:=[]; FacetsToFvector:=[]; Fvector2hvector:=[]; hvector2gvector:=[]; Suspension:=[]; Include_MoveOptions:=[]; 0_Move:=[]; Move:=[]; Ball_Boundary:=[]; ### Test_Object ### Test_Object := function() local element; Print("\n","Test_Object\n\n"); if log2file = 1 then PrintTo(file,"\n","Test_Object\n\n"); fi; facets:= # <--- Plug in the facets of your test object. [ [ 1, 2, 3, 4 ], [ 1, 2, 3, 15 ], [ 1, 2, 4, 5 ], [ 1, 2, 5, 11 ], [ 1, 2, 7, 11 ], [ 1, 2, 7, 13 ], [ 1, 2, 13, 14 ], [ 1, 2, 14, 15 ], [ 1, 3, 4, 15 ], [ 1, 4, 5, 10 ], [ 1, 4, 10, 15 ], [ 1, 5, 10, 11 ], [ 1, 6, 7, 10 ], [ 1, 6, 7, 12 ], [ 1, 6, 10, 15 ], [ 1, 6, 12, 15 ], [ 1, 7, 10, 11 ], [ 1, 7, 12, 13 ], [ 1, 12, 13, 15 ], [ 1, 13, 14, 15 ], [ 2, 3, 4, 5 ], [ 2, 3, 5, 6 ], [ 2, 3, 6, 12 ], [ 2, 3, 8, 12 ], [ 2, 3, 8, 14 ], [ 2, 3, 14, 15 ], [ 2, 5, 6, 11 ], [ 2, 6, 11, 12 ], [ 2, 7, 8, 11 ], [ 2, 7, 8, 13 ], [ 2, 8, 11, 12 ], [ 2, 8, 13, 14 ], [ 3, 4, 5, 6 ], [ 3, 4, 6, 7 ], [ 3, 4, 7, 13 ], [ 3, 4, 9, 13 ], [ 3, 4, 9, 15 ], [ 3, 6, 7, 12 ], [ 3, 7, 12, 13 ], [ 3, 8, 9, 12 ], [ 3, 8, 9, 14 ], [ 3, 9, 12, 13 ], [ 3, 9, 14, 15 ], [ 4, 5, 6, 7 ], [ 4, 5, 7, 8 ], [ 4, 5, 8, 14 ], [ 4, 5, 10, 14 ], [ 4, 7, 8, 13 ], [ 4, 8, 13, 14 ], [ 4, 9, 10, 13 ], [ 4, 9, 10, 15 ], [ 4, 10, 13, 14 ], [ 5, 6, 7, 8 ], [ 5, 6, 8, 9 ], [ 5, 6, 9, 15 ], [ 5, 6, 11, 15 ], [ 5, 8, 9, 14 ], [ 5, 9, 14, 15 ], [ 5, 10, 11, 14 ], [ 5, 11, 14, 15 ], [ 6, 7, 8, 9 ], [ 6, 7, 9, 10 ], [ 6, 9, 10, 15 ], [ 6, 11, 12, 15 ], [ 7, 8, 9, 10 ], [ 7, 8, 10, 11 ], [ 8, 9, 10, 11 ], [ 8, 9, 11, 12 ], [ 9, 10, 11, 12 ], [ 9, 10, 12, 13 ], [ 10, 11, 12, 13 ], [ 10, 11, 13, 14 ], [ 11, 12, 13, 14 ], [ 11, 12, 14, 15 ], [ 12, 13, 14, 15 ] ] # Example: 3-dimensional Klein bottle with 15 vertices. ; FacetsToFvector(); Fvector2hvector(); hvector2gvector(); maxvertex:=0; for element in faces_A[1] do if element[1] > maxvertex then maxvertex:=element[1]; fi; od; end; ### Reference_Object ### Reference_Object := function() local element, i, j, matrix; Print("\n","Reference_Object\n\n"); if log2file = 1 then PrintTo(file,"\n","Reference_Object\n\n"); fi; faces_B:=[]; faces_B[max]:= # <--- Plug in the facets of your reference object. [ [ 1, 2, 3, 5 ], [ 1, 2, 3, 8 ], [ 1, 2, 4, 5 ], [ 1, 2, 4, 9 ], [ 1, 2, 7, 8 ], [ 1, 2, 7, 9 ], [ 1, 3, 4, 5 ], [ 1, 3, 4, 9 ], [ 1, 3, 8, 9 ], [ 1, 6, 7, 8 ], [ 1, 6, 7, 9 ], [ 1, 6, 8, 9 ], [ 2, 3, 4, 6 ], [ 2, 3, 4, 9 ], [ 2, 3, 5, 6 ], [ 2, 3, 8, 9 ], [ 2, 4, 5, 6 ], [ 2, 7, 8, 9 ], [ 3, 4, 5, 7 ], [ 3, 4, 6, 7 ], [ 3, 5, 6, 7 ], [ 4, 5, 6, 8 ], [ 4, 5, 7, 8 ], [ 4, 6, 7, 8 ], [ 5, 6, 7, 9 ], [ 5, 6, 8, 9 ], [ 5, 7, 8, 9 ] ] # Example: 3-dimensional Klein bottle with unique minimal triangulation on 9 vertices. ; F_B:=[]; for i in [1..(max-1)] do faces_B[i]:=[]; for element in faces_B[max] do UniteSet(faces_B[i],Combinations(element,i)); od; F_B[i]:=Length(faces_B[i]); od; F_B[max]:=Length(faces_B[max]); # computing Altshuler-Steinberg determinant # matrix:=[]; for i in [1..Length(faces_B[1])] do matrix[i]:=[]; for j in [1..Length(faces_B[max])] do if IsSubset(faces_B[max][j],faces_B[1][i]) = true then matrix[i][j]:=1; else matrix[i][j]:=0; fi; od; od; det_B:=DeterminantMat(matrix*TransposedMat(matrix)); end; ######################################################################### ### Functions to compute the f,g,h-vectors ### ######################################################################### ### Function FacetsToFvector computes the F-vector from the facets ### ### (The f-vector is related to the F-vector by f_i = F_(i+1) ) ### FacetsToFvector := function() local element, k; ## Computing the dimension dim=max-1 of the simplicial complex. ## max:=0; for element in facets do if Length(element) > max then max:=Length(element); fi; od; dim:=max-1; Print("dim = ",dim,"\n\n"); if log2file = 1 then AppendTo(file,"dim = ",dim,"\n\n"); fi; ## Computing all faces ## faces_A:=[]; F_A:=[]; chi:=0; sum:=0; for k in [1..max] do faces_A[k]:=[]; for element in facets do if Length(element) >= k then UniteSet(faces_A[k],Combinations(element,k)); fi; od; F_A[k]:=Length(faces_A[k]); Print("f_",k-1," = ",F_A[k]," "); if log2file = 1 then AppendTo(file,"f_",k-1," = ",F_A[k]," "); fi; chi:=chi+((-1)^(k+1))*F_A[k]; sum:=sum+F_A[k]; od; Print("\n\n","chi = ",chi," ","sum = ",sum,"\n"); if log2file = 1 then AppendTo(file,"\n\n","chi = ",chi," ","sum = ",sum,"\n"); fi; end; ### Function Fvector2hvector converts the F-vector to the h-vector ### ### ( F --> h ) ### Fvector2hvector := function() local k, i; h:=[]; for k in [1..max] do h[k]:=(-1)^k*Binomial(max,k); for i in [1..max] do h[k]:=h[k]+(-1)^(k-i)*Binomial(max-i,max-k)*F_A[i]; od; od; end; ### Function hvector2gvector converts the h-vector to the g-vector ### ### ( h --> g ) ### hvector2gvector := function() local k; g:=[]; if QuoInt(max,2) >= 1 then g[1]:=h[1]-1; Print("\n","g_",1," = ",g[1]," "); if log2file = 1 then AppendTo(file,"\n","g_",1," = ",g[1]," "); fi; fi; for k in [2..QuoInt(max,2)] do g[k]:=h[k]-h[k-1]; Print("g_",k," = ",g[k]," "); if log2file = 1 then AppendTo(file,"g_",k," = ",g[k]," "); fi; od; Print("\n"); if log2file = 1 then AppendTo(file,"\n"); fi; end; ################################################################## ### Initional options for moves (and reverse moves) ### ### ( Reverse_k_Move = (max-k-1)-Move ) ### ################################################################## InitionalMoveOptions := function(r) local testelement, count, linkface, maxface; raw_options[r+1]:=[]; for testelement in faces_A[max-r] do linkface:=[]; count:=0; for maxface in faces_A[max] do if IsSubset(maxface,testelement) = true then count:=count+1; UniteSet(linkface,maxface); fi; od; if count = r + 1 then SubtractSet(linkface,testelement); AddSet(raw_options[r+1],[testelement,linkface]); fi; od; end; ################################################################## ### Include options for moves (and reverse moves) ### ################################################################## ### Include_MoveOptions ### Include_MoveOptions := function(r) local element; for element in raw_options[r+1] do if r = 0 then AddSet(options,element); elif not element[2] in faces_A[Length(element[2])] then AddSet(options,element); fi; od; end; ### Include_ReverseMoveOptions ### Include_ReverseMoveOptions := function(r) Include_MoveOptions(max-r-1); end; ################################################################### ### Moves (and reverse moves) ### ################################################################### ### 0_Move ### 0_Move := function() local element, i, A, linkface, maxface; maxvertex:=maxvertex+1; RemoveSet(faces_A[max],randomelement[1]); F_A[max]:=F_A[max]-1; RemoveSet(raw_options[1],randomelement); for i in [0..(max-1)] do for element in Combinations(randomelement[1],i) do A:=[maxvertex]; UniteSet(A,element); AddSet(faces_A[i+1],A); F_A[i+1]:=F_A[i+1]+1; linkface:=[]; for maxface in Combinations(randomelement[1],max-1) do if IsSubset(maxface,element) = true then UniteSet(linkface,maxface); fi; od; SubtractSet(linkface,element); AddSet(raw_options[max-Length(A)+1],[A,linkface]); od; od; ball_boundary_faces:=[]; for i in [1..(max-1)] do UniteSet(ball_boundary_faces,Combinations(randomelement[1],i)); od; Ball_Boundary(); end; ### Move ### Move := function(r) local element, i, j, A, count, maxface, linkface, new_facets, ball_interior_faces; if r = 0 then 0_Move(); else for i in [0..r] do for element in Combinations(randomelement[2],i) do A:=[]; UniteSet(A,randomelement[1]); UniteSet(A,element); RemoveSet(faces_A[max-r+i],A); F_A[max-r+i]:=F_A[max-r+i]-1; j:=1; while j <= Length(raw_options[max-Length(A)+1]) do if A = raw_options[max-Length(A)+1][j][1] then RemoveSet(raw_options[max-Length(A)+1], raw_options[max-Length(A)+1][j]); j:=Length(raw_options[max-Length(A)+1]); fi; j:=j+1; od; od; od; new_facets:=[]; ball_interior_faces:=[]; for i in [0..(max-r-1)] do for element in Combinations(randomelement[1],i) do A:=[]; UniteSet(A,randomelement[2]); UniteSet(A,element); AddSet(faces_A[r+i+1],A); F_A[r+i+1]:=F_A[r+i+1]+1; if i = max - r - 1 then AddSet(new_facets,A); else AddSet(ball_interior_faces,A); fi; od; od; for i in [0..(max-r-1)] do for element in Combinations(randomelement[1],i) do A:=[]; UniteSet(A,randomelement[2]); UniteSet(A,element); linkface:=[]; for maxface in new_facets do if IsSubset(maxface,A) = true then UniteSet(linkface,maxface); fi; od; SubtractSet(linkface,A); AddSet(raw_options[max-Length(A)+1],[A,linkface]); od; od; ball_boundary_faces:=[]; for element in new_facets do for i in [1..(max-1)] do UniteSet(ball_boundary_faces,Combinations(element,i)); od; od; SubtractSet(ball_boundary_faces,ball_interior_faces); Ball_Boundary(); fi; end; ### Ball_Boundary ### Ball_Boundary := function() local element, j, count, linkface, maxface; for element in ball_boundary_faces do count:=0; linkface:=[]; for maxface in faces_A[max] do if IsSubset(maxface,element) = true then count:=count+1; UniteSet(linkface,maxface); fi; od; SubtractSet(linkface,element); j:=1; while j <= Length(raw_options[max-Length(element)+1]) do if element = raw_options[max-Length(element)+1][j][1] then RemoveSet(raw_options[max-Length(element)+1], raw_options[max-Length(element)+1][j]); j:=Length(raw_options[max-Length(element)+1]); fi; j:=j+1; od; if count = max - Length(element) + 1 then AddSet(raw_options[max-Length(element)+1],[element,linkface]); fi; od; end; ################################################################### ### Test_Equivalent ### ################################################################### Test_Equivalent := function() local element, i, j, k, matrix, starA, starB, vertexB, H, stop_permutations, st, s, u, v, copyA, copyB, matched_verticesA, matched_verticesB, unmatched_verticesA, pairs, pair, linkelementA, linkelementB, co_facesA, co_elementA, co_elementB, intersection_co_facesA, flag_mismatch, new_vertexA, new_vertexB, permutedA, permuted_element; flag_equivalent:=0; Print(" F_A = ",F_A,"\n"); Print(" F_B = ",F_B,"\n"); if not F_A = F_B then flag_equivalent:=2; fi; if flag_equivalent = 0 then # computing Altshuler-Steinberg determinant # matrix:=[]; for i in [1..Length(faces_A[1])] do matrix[i]:=[]; for j in [1..Length(faces_A[max])] do if IsSubset(faces_A[max][j],faces_A[1][i]) = true then matrix[i][j]:=1; else matrix[i][j]:=0; fi; od; od; det_A:=DeterminantMat(matrix*TransposedMat(matrix)); Print(" det_A = ",det_A,"\n"); Print(" det_B = ",det_B,"\n"); if not det_A = det_B then flag_equivalent:=2; fi; fi; # test for combinatorial equivalence # if flag_equivalent = 0 then starA:=[]; for element in faces_A[max] do if faces_A[1][Length(faces_A[1])][1] in element then AddSet(starA,element); fi; od; H:=SymmetricGroup(max-1); for vertexB in faces_B[1] do if flag_equivalent = 0 then starB:=[]; for element in faces_B[max] do if vertexB[1] in element then AddSet(starB,element); fi; od; if Length(starA) = Length(starB) then stop_permutations:=0; st:=0; while st < Length(starB) and stop_permutations = 0 do st:=st+1; s:=0; while s < Factorial(max-1) and stop_permutations = 0 do s:=s+1; copyA:=[]; copyB:=[]; UniteSet(copyA,faces_A[max]); UniteSet(copyB,faces_B[max]); RemoveSet(copyA,starA[1]); RemoveSet(copyB,starB[st]); matched_verticesA:=[]; matched_verticesB:=[]; UniteSet(matched_verticesA,starA[1]); UniteSet(matched_verticesB,starB[st]); unmatched_verticesA:=[]; for element in faces_A[1] do UniteSet(unmatched_verticesA,element); od; SubtractSet(unmatched_verticesA,starA[1]); pairs:=[]; linkelementA:=[]; linkelementB:=[]; UniteSet(linkelementA,starA[1]); UniteSet(linkelementB,starB[st]); RemoveSet(linkelementA,faces_A[1][Length(faces_A[1])][1]); RemoveSet(linkelementB,vertexB[1]); AddSet(pairs,[faces_A[1][Length(faces_A[1])][1],vertexB[1]]); for k in [1..(max-1)] do AddSet(pairs,[linkelementA[k],linkelementB[k^Elements(H)[s]]]); od; co_facesA:=[]; UniteSet(co_facesA,Combinations(starA[1],max-1)); flag_mismatch:=0; while Length(unmatched_verticesA) > 0 and flag_mismatch = 0 do co_elementA:=[]; UniteSet(co_elementA,co_facesA[1]); u:=0; while u < Length(copyA) do u:=u+1; if IsSubset(copyA[u],co_elementA) then co_elementB:=[]; for pair in pairs do if pair[1] in co_elementA then AddSet(co_elementB,pair[2]); fi; od; new_vertexA:=[]; UniteSet(new_vertexA,copyA[u]); SubtractSet(new_vertexA,co_elementA); if new_vertexA[1] in unmatched_verticesA then v:=0; while v < Length(copyB) do v:=v+1; if IsSubset(copyB[v],co_elementB) then new_vertexB:=[]; UniteSet(new_vertexB,copyB[v]); SubtractSet(new_vertexB,co_elementB); if new_vertexB[1] in matched_verticesB then v:=Length(copyB); u:=Length(copyA); flag_mismatch:=1; else AddSet(pairs,[new_vertexA[1],new_vertexB[1]]); AddSet(matched_verticesA,new_vertexA[1]); AddSet(matched_verticesB,new_vertexB[1]); RemoveSet(unmatched_verticesA,new_vertexA[1]); UniteSet(co_facesA,Combinations(copyA[u],max-1)); RemoveSet(co_facesA,co_elementA); RemoveSet(copyA,copyA[u]); RemoveSet(copyB,copyB[v]); v:=Length(copyB); u:=Length(copyA); fi; fi; od; else for pair in pairs do if pair[1] = new_vertexA[1] then new_vertexB:=[pair[2]]; fi; od; AddSet(co_elementB,new_vertexB[1]); if co_elementB in copyB then intersection_co_facesA:=[]; UniteSet(intersection_co_facesA,co_facesA); IntersectSet(intersection_co_facesA,Combinations(copyA[u],max-1)); UniteSet(co_facesA,Combinations(copyA[u],max-1)); SubtractSet(co_facesA,intersection_co_facesA); RemoveSet(copyA,copyA[u]); RemoveSet(copyB,co_elementB); u:=Length(copyA); else u:=Length(copyA); flag_mismatch:=1; fi; fi; fi; od; od; if unmatched_verticesA = [] then permutedA:=[]; for element in faces_A[max] do permuted_element:=[]; for k in element do for pair in pairs do if k = pair[1] then AddSet(permuted_element,pair[2]); fi; od; od; AddSet(permutedA,permuted_element); od; if permutedA = faces_B[max] then flag_equivalent:=1; stop_permutations:=1; if rounds = 0 then Print(" combinatorially isomorphic\n"); for pair in pairs do Print(" ",pair[1]," --> ",pair[2],"\n"); od; fi; fi; fi; od; od; fi; fi; od; fi; if flag_equivalent = 1 then if rounds > 0 then Print(" bistellarly equivalent\n"); fi; no_options_flag:=1; else Print(" NOT equivalent\n"); fi; end; ################################################################### ################################################################### ### Main Part ### ################################################################### ################################################################### ### log to file ### log2file:=0; # <--- 0,1 file:=String("BISTELLAR_EQUIVALENT.doc"); ### fix random sequence ### RandomSeed(3); # <--- 1,2,3,4,... ### complexes ### Test_Object(); Reference_Object(); Test_Equivalent(); ### computing initional options for moves ### for i in [0..(max-1)] do InitionalMoveOptions(i); od; ### initional parameters ### rounds:=1; heating:=0; relaxation:=0; ######################################## ### Selection and execution of moves ### ######################################## while no_options_flag = 0 and rounds <= 50000 do # rounds <= 0,1,2,3,... <--- ### strategy for selecting options ### # <--- adapt bistellar flip strategy # in dimensions 2, 3, or 4 # or add a strategy for higher dimensions options:=[]; if dim = 2 then Include_ReverseMoveOptions(0); if options = [] then Include_MoveOptions(1); if options = [] then no_options_flag:=1; fi; fi; elif dim = 3 then if heating > 0 then Include_MoveOptions(1); if options = [] then Include_ReverseMoveOptions(1); heating:=0; fi; heating:=heating-1; else Include_ReverseMoveOptions(0); if options = [] then Include_ReverseMoveOptions(1); if options = [] then Include_MoveOptions(1); if relaxation = 10 then heating:=15; relaxation:=0; fi; relaxation:=relaxation+1; if options = [] then # Include_MoveOptions(0); no_options_flag:=1; fi; fi; fi; fi; elif dim = 4 then if heating > 0 then if IsInt(heating/20) = true and rounds <= 50000 then Include_MoveOptions(0); else Include_MoveOptions(1); Include_MoveOptions(2); if options = [] then Include_MoveOptions(0); fi; fi; heating:=heating-1; else Include_ReverseMoveOptions(0); if options = [] then Include_ReverseMoveOptions(1); if options = [] then Include_MoveOptions(1); Include_MoveOptions(2); if relaxation = 15 then heating:=20; relaxation:=0; fi; relaxation:=relaxation+1; if options = [] then no_options_flag:=1; fi; fi; fi; fi; else Print("\n","No bistellar flip strategy for ",dim, "-dimensional complexes available!!\n\n"); no_options_flag:=1; fi; ### choosing move at random ### if no_options_flag = 0 then randomelement:=RandomList(options); if Length(randomelement[1]) <= Int(max/2) then Move(max-Length(randomelement[1])); Print("\n", "Reverse-",Length(randomelement[1])-1,"-Move (",rounds," rounds)"); if log2file = 1 then AppendTo(file,"\n", "Reverse-",Length(randomelement[1])-1,"-Move (",rounds," rounds)"); fi; else Move(max-Length(randomelement[1])); Print("\n",max-Length(randomelement[1]),"-Move (",rounds," rounds)"); if log2file = 1 then AppendTo(file,"\n", max-Length(randomelement[1]),"-Move (",rounds," rounds)"); fi; fi; Fvector2hvector(); hvector2gvector(); Test_Equivalent(); rounds:=rounds+1; fi; od;