One Hat Cyber Team
Your IP :
216.73.216.115
Server IP :
194.44.31.54
Server :
Linux zen.imath.kiev.ua 4.18.0-553.77.1.el8_10.x86_64 #1 SMP Fri Oct 3 14:30:23 UTC 2025 x86_64
Server Software :
Apache/2.4.37 (Rocky Linux) OpenSSL/1.1.1k
PHP Version :
5.6.40
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
Macaulay2
/
View File Name :
Tropical.m2
newPackage( "Tropical", Version => "1.0", Date => "July 2019", Authors => { {Name => "Carlos Amendola", Email => "carlos.amendola@tum.de", HomePage=>""}, {Name => "Kathlen Kohn", Email => "kathlen.korn@gmail.com", HomePage=>""}, {Name => "Sara Lamboglia", Email => "lamboglia@math.uni-frankfurt.de", HomePage=>""}, {Name => "Diane Maclagan", Email => "D.Maclagan@warwick.ac.uk", HomePage=>"http://homepages.warwick.ac.uk/staff/D.Maclagan/"}, {Name => "Ben Smith", Email => "benjamin.smith-3@manchester.ac.uk", HomePage=>""}, {Name => "Jeff Sommars", Email => "sommars1@uic.edu", HomePage=>"http://homepages.math.uic.edu/~sommars"}, {Name => "Paolo Tripoli", Email => "paolo.tripoli@nottingham.ac.uk", HomePage=>"https://sites.google.com/view/paolotripoli/home"}, {Name => "Magdalena Zajaczkowska", Email => "Magdalena.A.Zajaczkowska@gmail.com", HomePage=>""} }, Headline => "computations in tropical geometry", Configuration => { "path" => "", "fig2devpath" => "", "keepfiles" => false, "cachePolyhedralOutput" => true, "tropicalMax" => false, "polymakeCommand" =>"" }, OptionalComponentsPresent => true, PackageExports => {"gfanInterface","EliminationMatrices","Matroids","Polyhedra"}, AuxiliaryFiles => true, CacheExampleOutput => true, Keywords => {"Tropical Geometry"} ) export{ "TropicalCycle", "tropicalCycle", "isBalanced", "tropicalPrevariety", "ComputeMultiplicities", "Prime", "stableIntersection", "tropicalVariety", "isTropicalBasis", "multiplicities", "IsHomogeneous", "Symmetry", "visualizeHypersurface", "Valuation", "BergmanFan" } polymakeCommand = (options Tropical)#Configuration#"polymakeCommand" polymakeOK = polymakeCommand != "" --Do we want to keep this? verboseLog = if debugLevel > 0 then printerr else identity if polymakeOK then verboseLog "polymake is installed" else verboseLog "polymake not present"; ------------------------------------------------------------------------------ -- CODE ------------------------------------------------------------------------------ --Polymake visualization for tropical hypersurfaces --inputs: p prime, x rational number --outputs: p-adic valuation of x pAdicVal = (p,x) -> ( num := numerator(x); denom := denominator(x); temp := p; if num%p===0 then (while (num%temp===0) do (temp=temp*p); return round(log(p,temp)-1)); if denom%p===0 then (while (denom%temp===0) do (temp=temp*p); return -round(log(p,temp)-1)); return 0; ) --inputs: p prime, polyn polynomial with p-adic coefficients --outputs: polynomial whose coefficients are valuations of coefficients of polyn pAdicCoeffs := (p,polyn) -> ( (M,C):=coefficients polyn; valuations := transpose matrix{apply(flatten entries C,i->pAdicVal(p,sub(i,QQ)))}; return (M,valuations); ) --inputs: parameter specifies the coefficient ring for polyn, polyn polynomial over coefficient ring --outputss: polynomial whose coefficients are valuations of coefficients of polyn polynomialCoeffs := (parameter,polyn) -> ( (M,C):=coefficients(Variables=>delete(parameter,gens class polyn),polyn); return (M,transpose matrix{apply(flatten entries C, i->min apply(exponents(polyn),sum))}); ) --inputs: var power of a monomial --outputs: term with power as coefficient expToCoeff = (var) -> ( temp := separate("^",toString(var)); if (length temp === 1) then return var else return concatenate(temp_1,temp_0); ) --inputs: polyn macaulay 2 polynomial --outputs: min of linear polynomials for polymake toTropPoly = method(TypicalValue=>String) toTropPoly (RingElement) := (polyn) ->( termList := apply(apply(terms polyn,toString),term->separate("*",term)); tropTerms := apply(apply(apply(termList, term->apply(term,expToCoeff)),term->between("+",term)),concatenate); return "min("|concatenate(between(",",tropTerms))|")"; ) --inputs: (termList,coeffs)=coefficients polynomial --outputs: min of linear polynomials for polymake toTropPoly (Matrix,Matrix) := (termList,coeffs) ->( noCoeffs := sum flatten entries termList; termString := apply(apply(terms noCoeffs,toString),term->separate("*",term)); tropTerms := apply(apply(apply(termString, term->apply(term,expToCoeff)),term->between("+",term)),concatenate); withCoeffs := for i when i<numColumns termList list toString((flatten entries coeffs)_i)|"+"|tropTerms_i; return "min("|concatenate(between(",",withCoeffs))|")"; ) --outputs: return Min or Max depending on the state of tropcailMax minmax = () -> (if (Tropical#Options#Configuration#"tropicalMax") then return "Max" else return "Min";) visualizeHypersurface = method(Options=>{ Valuation=>null }) visualizeHypersurface (RingElement) := o-> (polyn)->( polynomial := toTropPoly(polyn); if (instance(o.Valuation,Number)) then polynomial = toTropPoly(pAdicCoeffs(o.Valuation,polyn)); if (instance(o.Valuation,RingElement)) then polynomial = toTropPoly(polynomialCoeffs(o.Valuation,polyn)); if (instance(o.Valuation,String) and o.Valuation == "constant") then polynomial = toTropPoly(sum flatten entries (coefficients polyn)_0); print polynomial; filename := temporaryFileName(); filename << "use application 'tropical';" << endl << "visualize_in_surface(new Hypersurface<"|minmax()|">(POLYNOMIAL=>toTropicalPolynomial(\""|polynomial|"\")));" << close; runstring := polymakeCommand | " " |filename | " > "|filename|".out 2> "|filename|".err"; run runstring; removeFile (filename|".err"); removeFile (filename|".out"); removeFile (filename); ) --Example hypersurface --visualizeHypersurface("min(12+3*x0,-131+2*x0+x1,-67+2*x0+x2,-9+2*x0+x3,-131+x0+2*x1,-129+x0+x1+x2,-131+x0+x1+x3,-116+x0+2*x2,-76+x0+x2+x3,-24+x0+2*x3,-95+3*x1,-108+2*x1+x2,-92+2*x1+x3,-115+x1+2*x2,-117+x1+x2+x3,-83+x1+2*x3,-119+3*x2,-119+2*x2+x3,-82+x2+2*x3,-36+3*x3)") --opens in browser --Setting up the data type TropicalCycle TropicalCycle = new Type of MutableHashTable TropicalCycle.synonym = "tropical cycle" TropicalCycle.GlobalAssignHook = globalAssignFunction TropicalCycle.GlobalReleaseHook = globalReleaseFunction --basic operations on a tropical cycle tropicalCycle = method(TypicalValue => TropicalCycle) tropicalCycle (Fan, List) := (F,mult)->( if #maxCones(F) != #mult then error("The multiplicity list has the wrong length"); T := new TropicalCycle; T#"Multiplicities" = mult; T#"Fan" = F; return T ) --functions to switch to min-convention minmaxSwitch = method () minmaxSwitch (Fan) := F -> fanFromGfan({- rays F, linSpace F, maxCones F ,dim F,Polyhedra$isPure F,isSimplicial F,Polyhedra$fVector F}); minmaxSwitch (TropicalCycle) := T ->( tropicalCycle( minmaxSwitch fan T, multiplicitiesReorder({rays (minmaxSwitch fan T), maxCones (minmaxSwitch fan T),-rays T,maxCones T,multiplicities T}))) --Decide if a one-dimensional tropical cycle is balanced. --input: TropicalCycle T, which we assume is 1-dimensional isBalancedCurves = T ->( -- find first integer lattice points on each vector (get list of points) -- check whether sum * multiplicity is 0 -- assuming already have lattice points V = {...} m := multiplicities T; r := entries transpose rays T; (first unique sum(#r, i->(m_i * r_i))) == 0 ) --computes the star of the codimension-one polyhedron P in the tropical cycle Sigma star (TropicalCycle, Polyhedron) := (Sigma, P) -> ( --Create the linear space parallel to P --and quotient by it --Version for cones d:=dim P; V:= gens kernel transpose (rays(P)|linealitySpace(P)); B:=inverse(rays(P) | linealitySpace(P) | V); --version for polyhedral complex -- adjacentCells=select(maxPolyhedra(fan Sigma),sigma->(contains(sigma,P))); --version for fans, as currently implemented maxConesSigma:=facesAsCones(0, fan Sigma); adjacentCellsPos:=positions(maxConesSigma,sigma->(contains(sigma,P))); adjacentCells:=apply(adjacentCellsPos,i->(maxConesSigma_i)); raysStar:=apply(adjacentCells,sigma->( --Create vector pointing from P into sigma --version for Polyhedral complexes -- w:=interiorPoint(sigma)-interiorPoint(P); --version for fans w:=sum(rank source rays sigma, i->(rays sigma)_{i}) - sum(rank source rays P, i->(rays P)_{i}); --Project it onto ker(P) w=entries(B*w); w=posHull matrix apply(#w-d,i->(w_(i+d))) )); multsSigma:=multiplicities Sigma; multStar:=apply(adjacentCellsPos,i->(multsSigma_i)); return(tropicalCycle(fan raysStar,multStar)); ); isBalanced = method(TypicalValue => Boolean) isBalanced (TropicalCycle):= T->( if polymakeOK then ( --in polymake, the lineality span (1,...,1) is default. we embed the --fans in a higher dimensional fan in case our lineality span does not --contain (1,...,1) C := tropicalCycle(embedFan fan T, multiplicities T); -- parse object into a polymake script, run polymake and get result back from the same file (which got overwritten by polymake) filename := temporaryFileName(); filename << "use application 'tropical';" << endl << "my $c = "|convertToPolymake(C) << endl << "print is_balanced($c);" << endl; filename<<close; -- filename << "use strict;" << endl << "my $filename = '" << filename << "';" << endl << "open(my $fh, '>', $filename);" << endl; -- filename << "print $fh is_balanced($c);" << endl << "close $fh;" << endl << close; runstring := polymakeCommand | " "|filename | " > "|filename|".out 2> "|filename|".err"; run runstring; removeFile (filename|".err"); result := get (filename|".out"); removeFile (filename|".out"); removeFile (filename); if (substring(-4,result)=="true") then return true else if (substring(-5,result)=="false") then return false else if (substring(-1,result)=="1") then return true else if (substring(0,result)=="") then return false else return "Polymake throws an error"; ) else ( if dim T == 1 then return (isBalancedCurves T) else ( --loop over all co-dimension 1 faces F of T (use faces(ZZ, PolyhedralObject)) --for each F, compute star F / lineality space F (can use linSpace, write star of polyhedral complex) --use isBalancedCurves to check if balanced for all F d:=dim T; balanced:=true; F:= Polyhedra$faces(1, fan T); i:=0; while balanced and i<#F do ( --change next line when PolyhedralComplex change is made balanced = isBalancedCurves(star(T,polyhedronFromFace(fan T,F_i))); i=i+1; ); return balanced; ); ); ); --F is a fan and f is a list describing a face of F polyhedronFromFace = (F, f) -> ( L := linealitySpace F; R := rays F; ambientDim := numgens target rays F; origin := transpose matrix{apply(ambientDim, i -> 0)}; convexHull(origin, R_f, L) ); --Computing a tropical prevariety tropicalPrevariety = method(TypicalValue => Fan, Options => { --in the future, more strategies not dependent on "gfan" will be available Strategy=> "gfan" }) tropicalPrevariety (List) := o -> L -> ( gfanopt:=(new OptionTable) ++ {"tropicalbasistest" => false,"tplane" => false,"symmetryPrinting" => false, "symmetryExploit" => false,"restrict" => false,"stable" => false}; --using strategy gfan if (o.Strategy=="gfan") then ( F:= gfanTropicalIntersection(L, gfanopt); --gives only the fan and not the fan plus multiplicities which are wrongly computed in gfan if (Tropical#Options#Configuration#"tropicalMax" == true) then return F_0 else return minmaxSwitch (F_0)) else error "options not valid" ) tropicalPrevariety (List, List) := o -> (L, symmetryList) -> ( gfanopt:=(new OptionTable) ++ {"tropicalbasistest" => false,"tplane" => false,"symmetryPrinting" => false, "symmetryExploit" => true,"restrict" => false,"stable" => false}; --using strategy gfan if (o.Strategy=="gfan") then ( F:= gfanTropicalIntersection(L, symmetryList, gfanopt); --gives only the fan and not the fan plus multiplicities which are wrongly computed in gfan if (Tropical#Options#Configuration#"tropicalMax" == true) then return F_0 else return minmaxSwitch (F_0)) else error "options not valid" ) --Computing a tropical variety --The input is a matrix R, consisting of the rays of the variety, --a list of lists M, being the list of maximal cones, and a matrix L giving generators --for the lineality space. R has the first lattice point on rays as columns, while L has generators --for the lineality space as columns. --output:list of matrices whose rows span the span of each cone. -- note that ConesOfVariety is a local variable also in findMultiplicities computeCones=(R,M,L)->( ConesOfVariety:={}; i:=0; ConeOfVariety:={}; if M!={{}} then( --this i is going through the maximal cones while(i<#M) do( ConeOfVariety={}; j:=0; --this j is going through the rays inside the maximal cone you are in while(j<#M_i) do( --creates a list of rays ConeOfVariety=append(ConeOfVariety, R_(M_i_j)); j=j+1); -- creates a matrix whose rows are the rays of the cone ConeOfVariety= L|matrix ConeOfVariety; -- each cone has to contain also the lineality space since we are not quotienting by it -- ConeOfVariety = matrix ConeOfVariety ; --add the cone to the list of cones ConesOfVariety=append(ConesOfVariety,ConeOfVariety); i=i+1; ); ) else (ConesOfVariety={L}; ) ; ConesOfVariety ) --Compute the multiplicity of the cone spanned by the columns of the matrix M in trop(V(I)) findMultiplicity=(M,I)->( --compute vector w in relative interior in order to get the initial ideal in_w(I) with w in the maximal cone M w:=flatten entries(sum(numColumns M, j->M_{j})); --weight the ring according to this w , we are using leadTerm and max --convention since the input fan has not been changed to min --convention yet S:=ring I; R:=newRing(S, MonomialOrder=>{Weights=>w},Global=>false); J:=sub(I,R); K:=ideal(leadTerm(1,J)); --you saturate since you don't want the components outside the torus initialIdeal:= saturate(sub(K,S), product gens S); --this is the basis of the lattice associated to the toric ideal we are going to compute -- Basis:= (maxCol( generators kernel transpose M))_0; toricIdeal:= ideal apply(entries transpose gens kernel transpose M, u->( mon1:=1_R; mon2:=1_R; scan(numgens ring I,i->(if u_i>0 then mon1=mon1*R_i^(u_i) else mon2=mon2*R_i^(-u_i))); mon1-mon2 )); --this is where we used to use Binomials package -- toricIdeal:=saturate(latticeBasisIdeal(ring InitialIdeal,Basis),ideal product gens ring I); toricIdeal = saturate(toricIdeal,product gens R); m:=(degree(initialIdeal)/degree (toricIdeal)); --return multiplicity m as integer, since it lives currently in QQ --if m is an integer (as it should be), then the following command parses it to ZZ --otherwise, an errow will be returned "rational number is not an integer" lift(m,ZZ) ) --input Matrix whose columns are the generators of the cone and the ideal of the variety --output a list of one number that is the multiplicity --maths behind it look at exercise 34 chapter 3 Tropical book and [Stu96] --(Grobner basis and Convex Polytopes ) --input: the ideal of the variety and the fan computed by gfanbruteforce --output: list with the multiplicities to add to the tropicalCycle findMultiplicities=(I,T)->( ConesOfVariety:=computeCones( rays T,maxCones T, linSpace T); --creates a list with matrices that correspond to the maximal cones M:= apply(ConesOfVariety, linearSpan->( --for each cone computes the multiplicity and adds this to a list of multiplicities findMultiplicity(linearSpan,I)) ); M ) tropicalVariety = method(TypicalValue => TropicalCycle, Options => { ComputeMultiplicities => true, Prime => true, IsHomogeneous=>false, Symmetry => {} }) --Main function to call for tropicalVariety. Makes no assumption on ideal tropicalVariety (Ideal) := o -> (I) ->( local F; local T; newSymmetry:= o.Symmetry; --In case of homogenization we adjust the user given symmetries, recorded in the var newSymmetry. --If Symmetry present, check user has input permutations with the right length. If newSymmetry is {}, any always returns false. M := #(gens ring I); if any(newSymmetry, listPermutation -> #listPermutation != M) then error ("Length of permutations should be " | M); if o.IsHomogeneous==false then ( --First homogenize, append variable AA to the beginning R := ring I; AA := symbol AA; --Extend to a new coefficient ring. The added variable is at the beginning. S := first flattenRing(R[AA, Join =>false]); J:=substitute(I,S); J=homogenize(J,S_0); J=saturate(J,S_0); --we transform I in J so that the procedure continues as in the homogeneous case I=J; --If Symmetry present, adjust the symmetry vectors to the right length and shift the values up by one. If not present, this operates on an empty list. --Increase the values of these lists by 1. newSymmetry = for listPermutation in newSymmetry list --make a list with the following values apply(listPermutation, j -> j + 1); --Prepend a 0. newSymmetry = apply(newSymmetry, listPermutation -> prepend(0, listPermutation)); ); if (o.Prime== true) then ( cone := gfanTropicalStartingCone I; --check if resulting fan would be empty if instance(cone, String) then return cone; if(newSymmetry == {}) then F= gfanTropicalTraverse cone else F= gfanTropicalTraverse (cone, "symmetry" => newSymmetry); --check if resulting fan would be empty if (instance(F,String)) then return F; T=tropicalCycle(F_0,F_1)) else --If ideal not prime, use gfanTropicalBruteForce to ensure disconnected parts are not missed at expense of multiplicities (if o.ComputeMultiplicities==false then ( F= gfanTropicalBruteForce gfanBuchberger I; --check if resulting fan is empty if (instance(F,String)) then return F; mult := {}; i:=0; while(i<#maxCones (F))do( mult=append(mult,{}); i=i+1); T=tropicalCycle(F,mult) --note that the output of gfanTropicalBruteForce is a fan and an empty list of multiplicities this is why we have to add the right number of empty multiplicities ) else ( F= gfanTropicalBruteForce gfanBuchberger I; --check if resulting fan is empty if (instance(F,String)) then return F; --call the function tropicalCycle to create a new tropical variety with multiplicities T=tropicalCycle(F,findMultiplicities(I,F)) ); ); --Need to fix the paragraph below - why arewe doing all these checks when the --tropical variety is computed? if o.IsHomogeneous==false then ( newRays:=dehomogenise(rays T); newLinSpace:=gens gb dehomogenise(linealitySpace T); TProperties := {newRays, newLinSpace, maxCones T, dim(T)-1, Polyhedra$isPure fan T, isSimplicial T, drop(fVector T,1)}; UFan:=fanFromGfan(TProperties); U:= tropicalCycle(UFan,multiplicitiesReorder({rays UFan,maxCones UFan,newRays,maxCones T,multiplicities(T)})); -- we always want the output to be called T so we change U to T T=U; ); if (Tropical#Options#Configuration#"tropicalMax" == true) then return T else return minmaxSwitch T ) --auxiliary function to quotient out the lineality space (1,1,...1) introduced by the homogenisation --input= matrix whose columns are either the rays or the generators of the lineality space of a fan --output= matrix whose columns are either the rays or the generators of the lineality space of the fan quotiented by (1,...,1) dehomogenise=(M) -> ( vectorList:= entries transpose M; dehomog:= new List; for L in vectorList do ( newL := apply(#L-1,i->(L#(i+1)-L#0)); gcdL := gcd(newL); if gcdL==0 then continue; newL = newL/gcdL; newL = apply(newL,i->(lift(i,ZZ))); dehomog = append(dehomog,newL); ); if dehomog=={} then map(ZZ^(#entries(M)-1),ZZ^0,0) else transpose matrix dehomog ) --Check if a list of polynomials is a tropical basis for the ideal they generate --Current Strategy is using 'gfan' isTropicalBasis = method(TypicalValue => Boolean, Options => { Strategy=> "gfan" }) isTropicalBasis (List) := o -> L -> ( if (o.Strategy=="gfan") then ( gfanopt:=(new OptionTable) ++ {"tropicalbasistest" => true,"tplane" => false,"symmetryPrinting" => false,"symmetryExploit" => false,"restrict" => false,"stable" => false}; if not all(L, a-> isHomogeneous a) then error "Not implemented for non homogeneous polynomials yet"; return gfanTropicalIntersection(L, gfanopt) ) ) stableIntersection = method(TypicalValue => TropicalCycle, Options => {Strategy=> if polymakeOK then "atint" else "gfan"}) stableIntersection (TropicalCycle, TropicalCycle) := o -> (T1,T2) -> ( --TODOS: --4) gfan strategy outputs only a fan, not a tropical cycle --5) test cases --6) make tropical an immutable hash table if (o.Strategy=="atint") then ( --in polymake, the lineality span (1,...,1) is default. --we embed the fans in a higher dimensional fan in case our lineality span does not contain (1,...,1) C1 := tropicalCycle(embedFan fan T1, multiplicities T1); C2 := tropicalCycle(embedFan fan T2, multiplicities T2); filename := temporaryFileName(); --ugly declaration of helping strings openingStr := "\"_type SymmetricFan\\n\\nAMBIENT_DIM\\n\";"; dimStr := "\"\\n\\nDIM\\n\";"; linDimStr := "\"\\n\\nLINEALITY_DIM\\n\";"; raysStr := "\"\\n\\nRAYS\\n\";"; nRaysStr := "\"\\nN_RAYS\\n\";"; linSpaceStr := "\"\\n\\nLINEALITY_SPACE\\n\";"; orthLinStr := "\"\\n\\nORTH_LINEALITY_SPACE\\n\";"; fStr := "\"\\n\\nF_VECTOR\\n\";"; simpStr := "\"\\n\\nSIMPLICIAL\\n\";"; pureStr := "\"\\n\\nPURE\\n\";"; coneStr := "\"\\n\\nCONES\\n\";"; maxConeStr := "\"MAXIMAL_CONES\\n\";"; weightStr := "\"\\nMULTIPLICITIES\\n\";"; filename << "use application 'tropical';" << "my $c = "|convertToPolymake(C1) << "my $d = "|convertToPolymake(C2) << "my $i = intersect($c,$d);" << "use strict;" << "my $filename = '" << filename << "';" << "open(my $fh, '>', $filename);" << "print $fh " << openingStr << "print $fh $i->AMBIENT_DIM;" << "print $fh " << dimStr << "print $fh $i->DIM;" << "print $fh " << linDimStr << "print $fh $i->LINEALITY_DIM;" << "print $fh " << raysStr << "print $fh $i->RAYS;" << "print $fh " << nRaysStr << "print $fh $i->N_RAYS;" << "print $fh " << linSpaceStr << "print $fh $i->LINEALITY_SPACE;" << "print $fh " << orthLinStr << "print $fh $i->ORTH_LINEALITY_SPACE;" << "print $fh " << fStr << "print $fh $i->F_VECTOR;" << "print $fh " << simpStr << "print $fh $i->SIMPLICIAL;" << "print $fh " << pureStr << "print $fh $i->PURE;" << "print $fh " << coneStr << "my $cones = $i->CONES;" << "$cones =~ s/['\\>','\\<']//g;" << "print $fh $cones;" << "print $fh " << maxConeStr << "print $fh $i->MAXIMAL_CONES;" << "print $fh " << weightStr << "print $fh $i->WEIGHTS;" << "close $fh;" << close; runstring := polymakeCommand | " "|filename | " > "|filename|".out 2> "|filename|".err"; run runstring; result := get filename; removeFile (filename|".out"); removeFile (filename|".err"); removeFile (filename); parsedResult := gfanParsePolyhedralFan(result); if instance(parsedResult, String) then return parsedResult; (polyfan, mult) := parsedResult; --now we still need to transform things back to our format: --1) adjust the rays R := rays polyfan; row := (entries R)#0; ind := -1; scan(#row, i -> if ((row#i)==1) then ind = i); R = submatrix'(R, {0} , {ind}); --2)adjust the maximal cones C := maxCones polyfan; C = apply(C, c -> delete(ind, c)); C = apply(C, c -> apply(c, n -> if (n > ind) then (n-1) else (n) )); --3)adjust lineality space L := linSpace polyfan; L = submatrix'(L, {0} , ); -- L = L|(transpose matrix {apply(numgens target L , i -> 1)}); --4)inverse of our function embedFan F := unembedFan fan(R,L,C); return tropicalCycle (F,mult); ) else if (o.Strategy=="gfan") then ( F1 := fan(T1); m1 := multiplicities(T1); F2 := fan(T2); m2 := multiplicities(T2); return gfanStableIntersection(F1,m1,F2,m2); ) else ( return "Strategy unknown: Choose 'atint' or 'gfan'"; ); ) embedFan = F -> ( --embeds a fan into a fan of one dimension higher --and DOES NOT add the lineality space (1,...,1) --1) adjust rays rs := rays F; numberOfEntries := (numgens target rs)+1; rs = entries transpose rs; if (#rs != 0) then ( -- rs = apply(rs, s -> s|{-sum s}); rs = apply(rs, s -> s|{0}); -- numberOfEntries = #first(rs); rs = transpose matrix rs; ) else ( rs = matrix apply(numberOfEntries, i -> {}) ); --2) adjust lineality space ls := entries transpose linSpace F; if (#ls != 0) then( -- ls = apply(ls, s -> s|{-sum s}); ls = apply(ls, s -> s|{0}); -- ad := ambDim F; -- ls = ls|{apply(ad+1, i -> 1)}; ls = transpose matrix ls; ) else ( ls = matrix apply(numberOfEntries, i -> {}); ); return fan(rs,ls,maxCones F); ) unembedFan = F -> ( --inverse function to embedFan --1) adjust rays rs := entries transpose rays F; if (#rs != 0) then ( -- rs = apply(rs, s -> apply(s, i -> i-sum(s)/(#s))); rs = apply(rs, s -> apply(s, i -> i-last(s))); rs = apply(rs, s -> drop(s,-1)); -- rs = apply(rs, s -> apply(s, i -> i*(#s+1))); rs = transpose matrix rs; ) else ( rs = matrix apply(numgens(target rays F)-1, i -> {}); ); --2) adjust lineality space ls := entries transpose linSpace F; if (#ls != 0) then ( -- ls = apply(ls, s -> apply(s, i -> i-sum(s)/(#s))); ls = apply(ls, s -> apply(s, i -> i-last(s))); ls = apply(ls, s -> drop(s,-1)); -- ls = apply(ls, s -> apply(s, i -> i*(#s+1))); ls = transpose matrix ls; ) else ( ls = matrix apply(numgens(target rays F)-1, i -> {}); ); return fan(rs,ls,maxCones F); ) convertToPolymake = (T) ->( -- converts a tropical cycle into a string, which is a constructor of a tropical cycle in polymake -- F := fan(T); --check if given cycle is empty if (dim(F) < 0) then (return "new Cycle<Min>(PROJECTIVE_VERTICES=>[],MAXIMAL_POLYTOPES=>[],WEIGHTS=>[]);";) else ( --if not empty, check if min- or max-convention is used str := "new Cycle<"; if Tropical#Options#Configuration#"tropicalMax" then str=str|"Max" else str=str|"Min"; rs := entries transpose rays T; numberOfRays := #rs; ambientDim := ambDim F; --convert to polymake convention of rays: 1) add origin of the form (1,0,...,0) str = str|">(PROJECTIVE_VERTICES=>[[1"; local ray; scan (ambientDim,i -> str = str|",0"); str = str|"]"; --2) add every ray with a leading 0 scan (numberOfRays,i -> ( ray = rs#i; str = str|",[0"; scan (ambientDim,j -> str = str|","|ray#j); str = str|"]"; )); --every cone must now also be spanned by the origin str = str|"],MAXIMAL_POLYTOPES=>["; maxCs := maxCones(F); numberOfMaxCones := #maxCs; local cone; scan (numberOfMaxCones,i -> ( cone = maxCs#i; str = str|"[0"; scan (#cone,j -> str = str|","|(cone#j+1)); str = str|"],"; )); --delete last comma str = substring(0,#str-1,str); ls := entries transpose linSpace F; if (#ls != 0) then ( str = str|"],LINEALITY_SPACE=>["; --add lineality space scan (#ls, i -> ( ray = ls#i; str = str|"[0"; scan(#ray, j -> str = str|","|(ray#j)); str = str|"],"; )); --delete last comma str = substring(0,#str-1,str); ); str = str|"],WEIGHTS=>["; --the multiplicities stay unchanged mult := multiplicities(T); scan (numberOfMaxCones,i -> str = str|mult#i|","); str = substring(0,#str-1,str); str = str | "]);"; return str; ) ) --functions to get stuff from fans and tropical cycles rays TropicalCycle:= {} >> o -> T->( rays fan T) cones (ZZ,TropicalCycle):= (i,T)->( cones(i,fan T)) dim TropicalCycle:= T->( dim fan T) ambDim TropicalCycle:= T->( ambDim fan T) fVector (TropicalCycle) := T->(Polyhedra$fVector fan T) fan TropicalCycle := T -> (T#"Fan") linealitySpace (TropicalCycle):= T->( linSpace fan T) maxCones (TropicalCycle):= T->( maxCones fan T) multiplicities = method(TypicalValue => List) multiplicities (TropicalCycle) := T -> (T#"Multiplicities") isPure TropicalCycle := Boolean => T->( Polyhedra$isPure(fan(T))) isSimplicial TropicalCycle:= Boolean => T->( isSimplicial(fan(T))) -------------------- --Bergman fan code -------------------- -- BergmanconeC returns the matrix of generators of the cones -- corresponding to the chain of flats C. It does not check whether C -- is a chain of flats or not. BergmanconeC = (M, C) -> ( groundSetM:=#M.groundSet; L := {}; for F in C do( vect:={}; scan(groundSetM, i->( if member(i,F) then vect = append(vect,1) else vect = append(vect,0); )); L = append(L, vect) ); transpose matrix L ) -- BergmanFan returns the fan of a loopless well-defined matroid -- ground set must be [n] -- depends on functions above BergmanFan = (M) -> ( if ( loops(M) != {} ) then error("The current method only works for loopless matroids"); E := toList M.groundSet; L := {}; LM := latticeOfFlats M; redLM := dropElements(LM, {{}, E}); redOrdcplx := maximalChains redLM; allOnes := apply(E,i->1); for C in redOrdcplx do( L = append(L, coneFromVData(BergmanconeC(M,C),transpose matrix {allOnes})); ); F:= fan L; mults:=apply(#(maxCones F),i->1); tropicalCycle(F,mults) ) ---------------------------------------------------------------------------- ------------------------------------------------------------------------------ -- DOCUMENTATION ------------------------------------------------------------------------------ beginDocumentation() doc /// Key Tropical Headline the main M2 package for tropical computations Description Text This is the main M2 package for all tropical computations. This uses Anders Jensen's package gfan, Michael Joswig's package Polymake, and also internal M2 computations. The package defaults to using the min convention for tropical geometry. To switch to the max convention, reload the package using the command loadPackage("Tropical",Configuration=>{"tropicalMax"=>true}); The main command is @TO tropicalVariety@. To use the Polymake commands see the @TO "Polymake interface instructions"@. Text @SUBSECTION "Contributors"@ Text The following people have also contributed to the package: Text @UL { {HREF("https://users.math.yale.edu/~km995/","Kalina Mincheva")}, {HREF("http://www.math.unibe.ch/ueber_uns/personen/vargas_de_leon_alejandro/index_ger.html","Alejandro Vargas de Leon")}, {HREF("http://www.math.harvard.edu/~cmwang/","Charles Wang")}, {HREF("https://math.berkeley.edu/~yelena/", "Yelena Mandelshtam")}, {HREF("https://alessioborzi.github.io/", "Alessio Borzì")}, {HREF("https://www.linkedin.com/in/timothyxu/", "Timothy Xu")}, {HREF{"https://publish.uwo.ca/~aashra9/","Ahmed Umer Ashraf"}} }@ /// doc /// Key visualizeHypersurface (visualizeHypersurface,RingElement) Valuation Headline visualize the tropical hypersurface of the given polynomial Usage visualizeHypersurface(polyn) visualizeHypersurface(Valuation=>p,polyn) visualizeHypersurface(Valuation=>t,polyn) Inputs polyn: RingElement polynomial Valuation=>Number use p-adic coefficients with given p Valuation=>RingElement use coefficients in R[t] with given t Description Text This function wraps the Polymake visualization for a tropical hypersurface given an input polynomial. The input should be entered as a homogeneous polynomial. Running this method opens an image in a new browser window. The coefficients can be interpreted as p-adic coefficients or as polynomials via the option @TO Valuation@. Examples are commented out because they open a new browser window. Example --Examples are commented because they open in browser. Uncomment to run. R=ZZ[x,y,z] f=2*x*y+x*z+y*z+z^2 --visualizeHypersurface(Valuation=>2,f) f=2*x^2+x*y+2*y^2+x*z+y*z+2*z^2 --visualizeHypersurface(f) R=ZZ[w,x,y,z] f=8*x^2+8*y^2+8*z^2+8*w^2+2*x*y+2*x*z+2*y*z+2*x*w+2*y*w+2*z*w --visualizeHypersurface(f) /// doc /// Key TropicalCycle Headline a Type for working with tropical cycles Description Text This is the main type for tropical cycles. A TropicalCycle consists of a Fan with an extra HashKey Multiplicities, which is the list of multiplicities on the maximal cones listed in the order that the maximal cones appear in the MaxCones list. A TropicalCycle is saved as a hash table which contains the Fan and the Multiplicities. /// doc /// Key tropicalCycle (tropicalCycle, Fan, List) Headline constructs a TropicalCycle from a Fan and a list with multiplicities Usage tropicalCycle(F,mult) Inputs F:Fan mult:List Outputs T:TropicalCycle Description Text This function creates a tropical cycle from a fan and a list of multiplicities. The multiplicities must be given in the same order as the maximal cones appear in the MaximalCones list. Example F = fan {posHull matrix {{1},{0},{0}}, posHull matrix {{0},{1},{0}}, posHull matrix {{0},{0},{1}}, posHull matrix {{-1},{-1},{-1}}} mult = {1,2,-3,1} tropicalCycle(F, mult) /// doc/// Key isBalanced (isBalanced, TropicalCycle) Headline checks whether a tropical cycle is balanced Usage isBalanced T Inputs T:TropicalCycle Outputs B:Boolean Description Text This function checks if a tropical cycle is balanced. Example QQ[x,y,z] V = tropicalVariety(ideal(x+y+z)) isBalanced V F = fan {posHull matrix {{1},{0},{0}}, posHull matrix {{0},{1},{0}}, posHull matrix {{0},{0},{1}}, posHull matrix {{-1},{-1},{-1}}} mult = {1,2,-3,1} isBalanced (tropicalCycle(F, mult)) /// doc/// Key tropicalPrevariety (tropicalPrevariety, List) (tropicalPrevariety, List, List) [tropicalPrevariety, Strategy] Headline the intersection of the tropical hypersurfaces Usage tropicalPrevariety(L) tropicalPrevariaty(L,LS) tropicalPrevariety(L,Strategy=>S) tropicalPrevariety(L,LS,Strategy=>S) Inputs L:List of polynomials LS: List of Symmetries (optional) Strategy=>String Strategy (currently only "gfan") Outputs F:Fan the intersection of the tropical hypersurfaces of polynomials in L Description Text This method intersects the tropical hypersurfaces coming from the tropicalizations of the polynomials in the list L. If there are symmetries that leave the specified polynomials fixed, they can be specified by passing a list with the symmetries as second argument, with the same format as the option @TO Symmetry@. Example QQ[x_1,x_2,x_3,x_4] L={x_1+x_2+x_3+x_4,x_1*x_2+x_2*x_3+x_3*x_4+x_4*x_1,x_1*x_2*x_3+x_2*x_3*x_4+x_3*x_4*x_1+x_4*x_1*x_2,x_1*x_2*x_3*x_4-1} tropicalPrevariety L QQ[x_0,x_1] tropicalPrevariety({x_0+x_1+1}, {{1,0}}) QQ[x_0,x_1] tropicalPrevariety({x_0+x_1+1,x_0+x_1},Strategy => "gfan") /// doc/// Key tropicalVariety (tropicalVariety, Ideal) [tropicalVariety, ComputeMultiplicities] [tropicalVariety, Prime] [tropicalVariety, IsHomogeneous] [tropicalVariety, Symmetry] Headline the tropical variety associated to an ideal Usage tropicalVariety(I) tropicalVariety(I,ComputeMultiplicities=>true) tropicalVariety(I,Prime=>true) tropicalVariety(I,IsHomogeneous=>false) tropicalVariety(I,Symmetry=>{{...},{...}}) Inputs I:Ideal of polynomials IsHomogeneous=>Boolean that ensures whether the ideal is already homogeneous ComputeMultiplicities=>Boolean that confirms whether the multiplicities will be computed Prime=>Boolean that ensures whether the ideal is already prime Symmetry=>List that records the symmetries of the ideal Outputs F:TropicalCycle Description Text This method takes an ideal and computes the tropical variety associated to it. By default the ideal is assumed to be prime. If this is not the case the default answer will not necessarily give the correct answer. In this case use the optional argument Prime=>false. By default the tropicalVariety command computes multiplicities but setting computeMultiplicities=>false turns this off. This only saves time if Prime is set to false. The ideal I is not assumed to be homogeneous. The optional argument IsHomogeneous=>true allows the user to assert that the ideal is homogeneous. If there are symmetries of the ring corresponding to I that leave I fixed, they can be specified with the option @TO Symmetry@. Example QQ[x,y]; I=ideal(x+y+1); T=tropicalVariety(I); rays(T) maxCones(T) linealitySpace T Polyhedra$fVector fan T multiplicities(T) QQ[x,y,z,w]; I = ideal(w+x+y+z) T = tropicalVariety(I, IsHomogeneous=>true, Symmetry=>{{1,0,2,3},{2,1,0,3},{3,1,2,0}}) rays(T) maxCones(T) I=intersect(ideal(x+y+z+w),ideal(x-y,y-z)); T= tropicalVariety(I,Prime=>false); rays(T) maxCones(T) multiplicities(T) linealitySpace T QQ[x,y,z,w]; I=intersect(ideal(x+y+z+1),ideal(x^2-y*z)); T= tropicalVariety(I,Prime=>false,ComputeMultiplicities=>false); rays(T) maxCones(T) linealitySpace T multiplicities(T) /// doc/// Key stableIntersection (stableIntersection,TropicalCycle,TropicalCycle) [stableIntersection, Strategy] Headline computes the stable intersection of two tropical varieties Usage stableIntersection(F,G) stableIntersection(L,Strategy=>S) Inputs F:TropicalCycle a tropical cycle G:TropicalCycle another tropical cycle Strategy=>String Strategy ("atint" (polymake) or "gfan") Outputs T:TropicalCycle a tropical cycle Description Text This computes the stable intersection of two tropical cycles. For details on the definition of stable intersection, see, for example, Section 3.6 of TROPICALBOOK. If a recent enough version of polymake is installed, the Strategy "atint" is default. Otherwise "gfan" will be used, which only computes the fan of the stable intersection without multiplicities. Example QQ[x,y,z]; I = ideal(x^2+y^2+z^2-1); T1 = tropicalVariety(I); J = ideal(x*y+y*z+x*z+1); T2 = tropicalVariety(J); V = tropicalVariety(I+J); -- W1 = stableIntersection(T1,T2,Strategy=>"atint"); W2 = stableIntersection(T1,T2,Strategy=>"gfan"); -- V#"Fan" == W1#"Fan" -- V#"Multiplicities" == W1#"Multiplicities" V#"Fan" == W2 /// doc/// Key isTropicalBasis (isTropicalBasis, List) [isTropicalBasis, Strategy] Headline checks if a list of polynomials is a tropical basis for the ideal they generate Usage isTropicalBasis(L) isTropicalBasis(L,Strategy=>S) Inputs L:List of polynomials Strategy=>String Strategy (currently only "gfan") Outputs F:Boolean whether the list of polynomials is a tropical basis for the ideal it generates Description Text This method checks if the intersection of the tropical hypersurfaces associated to the polynomials in the list equals the tropicalization of the variety corresponding to the ideal they generate. Example QQ[x,y,z] isTropicalBasis({x+y+z,2*x+3*y-z}) isTropicalBasis(flatten entries gens Grassmannian (1,4,QQ[a..l])) /// doc/// Key multiplicities (multiplicities, TropicalCycle) Headline returns the list of multiplicities on maximal cones in a tropical cycle Usage multiplicities(T) Inputs T:TropicalCycle Outputs L:List Description Text This method returns the list of multiplicities on maximal cones in a tropical cycle. Example QQ[x,y,z] V = tropicalVariety(ideal(x+y+z)); multiplicities V /// doc/// Key ComputeMultiplicities Headline option to compute the multiplicities in case they ideal is not prime Usage tropicalVariety(I,ComputeMultiplicities=>true) Description Text This option allows to compute the multiplicities in case the ideal I is not prime. In fact the output of gfan does not include them and hence they are computed separately by this package. By default the ideal is assumed to be prime. Example QQ[x,y,z]; I=ideal(x^2-y^2); isPrime I T=tropicalVariety(I,Prime=>false,ComputeMultiplicities=>true); rays T maxCones T multiplicities T /// doc/// Key Prime Headline option to declare if the input ideal is prime Usage tropicalVariety(I,Prime=>false) Description Text By default the ideal is assumed to be prime. If the ideal is not prime then the internal procedure to compute the tropicalization is different. It is used gfan_tropicalbrute force instead of gfan_tropicaltraverse. Example QQ[x,y,z]; I=ideal(x^2+y^2-2*x*y); isPrime I T=tropicalVariety(I,Prime=>false) /// doc/// Key IsHomogeneous Headline option to declare if the input ideal is homogeneous Usage tropicalVariety(I,IsHomogeneous=>true) Description Text If the option is used than homogeneity of the ideal is not tested. By default the ideal is always assumed not homogeneous and a test is performed before applying the function tropicalVariety. Example QQ[x,y]; I=ideal(x+y+1); T=tropicalVariety (I,IsHomogeneous=>false) /// doc/// Key Symmetry Headline option to declare if the input ideal has symmetries Usage tropicalVariety(I,Symmetry=>{{..},{..}}) Description Text If the option is used, the specified symmetries are used in the calculation of the tropical variety. For an ideal I of a polynomial ring R = KK[x_0 .. x_N], each symmetry is a permutation encoded in a list \{s_0, s_1, ..., s_N\} of numbers from 0 to N which records that swapping the variable x_j with the variable x_{s_j} in R leaves the ideal I fixed. Exploiting symmetries reduces the number of computations needed. The length of each symmetry equals the number of generators of R, otherwise an error is raised. Example QQ[x_0,x_1,x_2]; I=ideal(x_0+x_1+x_2+1); T=tropicalVariety (I,Symmetry=>{{1,0,2}, {2,1,0} }) /// doc/// Key (fan,TropicalCycle) Headline outputs the fan associated to the tropical cycle Usage fan(T) Inputs T:TropicalCycle Outputs F:Fan the fan associated to the tropical cycle T Description Text This function outputs the fan associated to the tropical cycle T. Example QQ[x,y,z] T=tropicalVariety (ideal(x+3*y+3)); fan T peek o3#cache /// doc/// Key (maxCones,TropicalCycle) Headline computes the maximal cone of a tropical cycle Usage maxCones(T) Inputs T:TropicalCycle Outputs L:List Description Text This function computes the maximal cones of the fan associated to the tropical cycle. Example QQ[x,y,z,w] I=ideal(x^2-y*z+w^2,w^3-x*y^3+z^3); T=tropicalVariety I; maxCones T /// doc/// Key (isPure,TropicalCycle) Headline checks whether a tropical cycle is pure Usage isPure(T) Inputs T:TropicalCycle Outputs B:Boolean Description Text This function checks whether the fan associated to the tropical cycle is pure, i.e. if the maximal cones have all the same dimension. Example F=fan ({posHull(matrix{{1,2,3},{0,2,0}}),posHull(matrix{{0},{1}})}); T=tropicalCycle (F,{1,2}); isPure T /// doc/// Key (isSimplicial,TropicalCycle) Headline checks whether a tropical cycle is simplicial Usage isSimplicial(T) Inputs T:TropicalCycle Outputs B:Boolean Description Text This function checks if the fan associated to the tropical cycle T is simplicial, i.e. if for each cone the rays generating it are linearly independent. Example F=fan ({posHull(matrix{{1,2,3},{0,2,0}}),posHull(matrix{{0},{1}})}); T=tropicalCycle (F,{1,2}); isSimplicial T /// doc/// Key (rays,TropicalCycle) Headline computes the rays of a tropical cycle Usage rays(T) Inputs T:TropicalCycle Outputs M:Matrix Description Text This function computes the rays of the fan associated to the tropical cycle. These are the columns of the output matrix. Example QQ[x,y,z,w] I=ideal(x^2-y*z+w^2,w^3-x*y^3+z^3); T=tropicalVariety I; rays T /// doc/// Key (dim,TropicalCycle) Headline computes the dimension of a tropical cycle Usage dim(T) Inputs T:TropicalCycle Outputs k:ZZ the dimension of the tropical cycle T Description Text This function computes the dimension of the fan associated to the tropical cycle T. Example QQ[x,y,z,w] I=ideal(x^2-y*z+w^2,w^3-y^3*x+z^3); T=tropicalVariety I; dim T /// doc/// Key (fVector,TropicalCycle) Headline computes the fVector of a tropical cycle Usage fVector(T) Inputs T:TropicalCycle Outputs L:List the fVector of the fan associated to the tropical cycle T Description Text This function computes the fVector of the fan associated to the tropical cycle T. Example QQ[x,y,z] T=tropicalVariety (ideal(x+3*y+3)); fVector T /// doc/// Key (ambDim,TropicalCycle) Headline computes the dimension of the ambient space of a tropical cycle Usage ambDim(T) Inputs T:TropicalCycle Outputs n:ZZ the dimension of the tropicalCycle T Description Text This function computes the dimension of the space where the tropical cycle is contained. Example QQ[x,y,z] T=tropicalVariety(ideal(x+y+z)); ambDim T /// doc/// Key (cones,ZZ,TropicalCycle) Headline computes the cones of a tropical cycle Usage cones(k,T) Inputs k:ZZ T:TropicalCycle Outputs L:List the cones of codimension k in T Description Text This function computes the cone of codimension k of the fan associated to the tropical cycle T. Example QQ[x,y,z,w,t] I=ideal(x^2-y*z+w^2,w^3-y^3*x+z^3,t-w+x); T=tropicalVariety I; cones(2,T) /// doc/// Key (linealitySpace,TropicalCycle) Headline computes the lineality space of a tropical cycle Usage linealitySpace(T) Inputs T:TropicalCycle Outputs M:Matrix Description Text This function computes the lineality space of the fan associated to the tropical cycle T. The generators of the lineality space are the columns of the output matrix Example QQ[x,y,z]; I=ideal(x-y); T=tropicalVariety I; L=linealitySpace T /// doc/// Key "Polymake interface instructions" Headline instructions for loading Polymake with this package. Description Text The software program Polymake is not distributed with Macaulay2, so to use the Polymake commands the user needs to install Polymake on their own machine, and tell Macaulay2 where to find it. This is done with the Configuration option "polymakeCommand". The default is that this is empty, which means that Polymake options will not be used. To tell the package where your copy of Polymake is installed, use either loadPackage("Tropical",Configuration=>\{"polymakeCommand"=>"YOUR COMMAND"\}), or edit the init-Tropical.m2 file (created after you install the package) by changing "polymakeCommand" => "", into "polymakeCommand" => "YOUR COMMAND" On a Mac, the default value for YOUR COMMAND is /Applications/polymake.app/Contents/MacOS/polymake.start and the init-Tropical.m2 file is usually in ~/Library/Application Support/Macaulay2. On Unix, the default value for YOUR COMMAND is /usr/bin/polymake and the init-Tropical.m2 file is usually in ~/.Macaulay2. If polymake is installed in a nonstandard location, you can find YOUR COMMAND with the terminal command "which polymake". This package should work with Polymake versions > 3.2, and has been tested up to 4.2. /// doc/// Key BergmanFan Headline the Bergman fan of a matroid Usage BergmanFan(M) Inputs M:Matroid Outputs T:TropicalCycle Description Text Computes the Bergman fan of a matroid, with the fine fan structure. This uses the Matroids package; the input should be a matroid in the sense of that package. The output is a tropical cycle T whose underlying fan is the fine fan structure in the sense of Ardila-Klivans on the Bergman fan of the matroid. This has underlying simplicial complex the order complex of the lattice of flats of the matroid M. If the ground set of the matroid has size n, then the fan given is in R^n, so there is always a lineality space of dimension at least one. Example M=uniformMatroid(2,3); T=BergmanFan(M); rays T maxCones T linealitySpace T /// ----- TESTS ----- ----------------------- --tropicalCycle ----------------------- TEST /// F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) assert((tropicalCycle(F,{1,1,1}))#"Fan"== F) assert((tropicalCycle(F,{1,1,1}))#"Multiplicities"== {1,1,1}) /// ----------------------- --isTropicalBasis ----------------------- TEST /// assert(isTropicalBasis (flatten entries gens Grassmannian(1,4,QQ[a..l]))==true) R:=QQ[x,y,z] assert( not isTropicalBasis({x+y+z,2*x+3*y-z})) /// ----------------------- --getters ----------------------- --rays TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((rays T)==( matrix{{0,0,0},{1,-1,0},{0,-1,1}})) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((rays(T))==(matrix {{}, {}, {}})) /// --maxCones TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert(sort(maxCones T)==( sort({{0,1},{0,2},{1,2}}))) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((maxCones(T))==({{}})) /// --dim TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((dim T)==( 3)) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((dim T)==(1)) /// --ambDim TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((ambDim T)==( 3)) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((ambDim T)==(3)) /// --fVector TEST/// T1:=new TropicalCycle G:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T1#"Multiplicities" ={1,1,1}; T1#"Fan" = G; assert((fVector T1)==( {0, 1, 3, 3})) G=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T1#"Multiplicities" ={1}; T1#"Fan" = G; assert((fVector T1)==({0,1})) /// --linealitySpace TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((linealitySpace T)==( matrix{{1},{1},{1}})) F=fan(matrix{{1,0,-1},{0,1,-1}},map(ZZ^2,ZZ^0,0),{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((linealitySpace T)==(0)) /// --multiplicities TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((multiplicities T)==( {1,1,1})) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((multiplicities T)==({1})) /// --fan TEST/// T=new TropicalCycle F=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((fan T)==(F)) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((fan T)==(F)) /// --cones TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert((cones(1,T))==({{}})) assert((cones(2,T))==({{0},{1},{2}})) assert((cones(3,T))==({{0,1},{0,2},{1,2}})) F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}}) T#"Multiplicities" ={1}; T#"Fan" = F; assert((cones(1,T))==({{}})) /// ----------------------- --isBalanced ----------------------- TEST/// F=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}); T= tropicalCycle(F,{1,1,1}); assert(isBalanced T) T2 = tropicalCycle(F,{1,2,3}); assert(not isBalanced T2); /// TEST/// R=QQ[x,y,z]; V = tropicalVariety(ideal(x+y+z)) assert(isBalanced V) G = V; G#"Multiplicities" = {1,2,1} assert(not isBalanced G) /// TEST/// S = QQ[x,y]; V = tropicalVariety(ideal(x+y+1)) assert(isBalanced V) /// TEST/// F = fan {posHull matrix {{1},{0},{0}}, posHull matrix {{0},{1},{0}}, posHull matrix {{0},{0},{1}}, posHull matrix {{-1},{-1},{-1}}} mult = {1,2,-3,1} assert(not isBalanced (tropicalCycle(F, mult))) /// ----------------------- --tropicalPrevariety ----------------------- TEST/// QQ[x,y,z,w] F=tropicalPrevariety({x+y+z+w,x^2+y*z}) assert((rays F) == matrix {{1,1,-1},{5,-3,-1},{-3,5,-1},{-3,-3,3}}) /// TEST/// QQ[x,y,z,w] F=tropicalPrevariety({x+y+z+w,x^2+y*z}, {{0,2,1,3}}) assert((rays F) == matrix {{1,1,-1},{5,-3,-1},{-3,5,-1},{-3,-3,3}}) /// TEST/// QQ[x,y] F=tropicalPrevariety({x+y+1}, {{1,0}}) assert((rays F) == matrix {{1,-1,0},{0,-1,1}}) /// ----------------------- --stableIntersection ----------------------- TEST/// F=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}); T= tropicalCycle(F,{1,1,1}); T2= stableIntersection(T,T,Strategy=>"gfan") assert(dim T2 == 3) assert(maxCones T2 == {{1, 2}, {0, 2}, {0, 1}}) /// if polymakeOK then ( TEST/// F1:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}); T1:= tropicalCycle(F1,{1,1,1}); R1:= stableIntersection(T1,T1,Strategy=>"atint"); R2:= stableIntersection(T1,T1,Strategy=>"gfan"); assert(R1#"Fan" == R2) assert(dim R2 == 3) assert(maxCones R2 == {{1, 2}, {0, 2}, {0, 1}}) R =QQ[x,y,z,t]; I=ideal(x+y+z+t); J=ideal(4*x+y-2*z+5*t); T1 = stableIntersection(tropicalVariety(I),tropicalVariety(J)); T2 = tropicalVariety(I+J); assert(T1#"Fan" == T2#"Fan") assert(T1#"Multiplicities" == T2#"Multiplicities") R = QQ[x,y,z]; I = ideal(x^2+y^2+z^2-1); T1 = tropicalVariety(I); J = ideal(x*y+y*z+x*z+1); T2 = tropicalVariety(J); V = tropicalVariety(I+J); W1 = stableIntersection(T1,T2,Strategy=>"gfan"); W2 = stableIntersection(T1,T2,Strategy=>"atint"); assert(V#"Fan" == W1) assert(V#"Fan" == W2#"Fan") assert(V#"Multiplicities" == W2#"Multiplicities") /// ) ----------------------- --tropicalVariety ----------------------- TEST/// QQ[x,y,z,w] --homogeneous I=ideal(x^2+y^2+z^2) T:=tropicalVariety(I) assert ((rays T)==(matrix {{2, -1, -1},{-1, 2, -1}, {-1, -1, 2}, {0, 0, 0}})) assert((linealitySpace T)==( matrix {{1, 0}, {1, 0}, {1, 0}, {0, 1}})) assert((multiplicities T)==( {2,2,2})) assert((maxCones T)==( {{0},{1},{2}})) --homogeneous and binomial I=ideal(x^2+x*z) T=tropicalVariety (I,Prime=>false) assert ((rays T)==(0 )) assert((linealitySpace T)==( matrix {{0, 1, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}})) assert((maxCones T)==( {{}})) assert((multiplicities T)==( {1})) T=tropicalVariety (I,Prime=>false,ComputeMultiplicities=>false) assert ((rays T)==(0)) assert((linealitySpace T)==( matrix {{0, 1, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}})) assert((maxCones T)==( {{}})) assert((multiplicities T)==( {{}})) --non homogeneous I=ideal(x^2-y*z+w^2,w^3-y^3*x+z^3) T=tropicalVariety(I) assert((rays T)== (matrix {{-6, -3, 0, 1, 3, 6}, {-5, -2, -1, 1, 2, 5}, {-7, -3, -1, 1, 4, 7}, {-6, -3, -1, 1, 3, 7}})) assert((linealitySpace T)==(0)) assert((maxCones T)==( {{0, 1}, {0, 2}, {0, 5}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 5}, {4, 5}})) assert((multiplicities T)==( {2, 1, 1, 6, 3, 2, 1, 3, 1})) QQ[x,y,z] --non homogeneous I=ideal(x*y-y+1) T=tropicalVariety(I) assert ((rays T)== (matrix {{-1, 0, 3}, {1, -3, 0}, {0, -1, 1}})) assert((linealitySpace T)==( matrix {{0}, {0}, {1}} )) assert((maxCones T)==( {{1}, {0}, {2}})) assert((multiplicities T)==( {1, 1, 1})) --symmetry and homogeneous QQ[x,y, z] I=ideal(x^2+y^2+z^2) G=tropicalVariety(I, Symmetry=>{{1, 0, 2}, {1, 2, 0}, {2, 0, 1}}) assert ((rays G)==(matrix {{2, -1, -1},{-1, 2, -1}, {-1, -1, 2}})) --symmetry and non-homogeneous QQ[x,y] G=tropicalVariety(ideal(x+y+1), Symmetry=>{{1,0}}) assert((rays G) == matrix {{1,-1,0},{0,-1,1}}) /// ----------------------- --findMultiplicities --findMultiplicity --computeCones ----------------------- ----------------------- --isPure ----------------------- TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert(isPure(T)==(true)) F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0},{1,2}}) T#"Multiplicities" ={1,1}; T#"Fan" = F; assert(isPure(T)==(false)) /// ----------------------- --isSimplicial ----------------------- TEST/// T:=new TropicalCycle F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}}) T#"Multiplicities" ={1,1,1}; T#"Fan" = F; assert(isSimplicial(T)==(true)) F:=fan(matrix{{0,0,0,0},{1,0,-1,2},{0,1,-1,1}},matrix{{1},{1},{1}},{{0,1,2},{0,1,3},{0,2,3},{1,2,3}}); T#"Multiplicities" ={1,1,1,1}; T#"Fan" = F; assert(isSimplicial(T)==(false)) /// ----------------------- --BergmanFan ----------------------- TEST/// U24 = uniformMatroid(2,4) F = BergmanFan U24 ray = rays F mC = maxCones F l = sort(flatten(mC)) assert(ray*transpose(matrix({{1,1,1,1}})) == 0) assert(l == toList(0..3)) assert(isBalanced(F)==(true)) /// TEST/// A=transpose matrix{{1,0,0},{1,1,0},{1,2,0},{1,0,1},{1,2,1},{1,0,2}}; M=matroid(A); T=BergmanFan M; R=rays T; assert(rank source R ==17) assert(dim(T)==rank(A)) /// ----------------------- --convertToPolymake ----------------------- ----------------------- --star ----------------------- TEST /// R=QQ[x,y,z]; I=ideal(x+y+z+1); T=tropicalVariety(I); P=convexHull(matrix{{0},{0},{0}}, matrix{{1},{0},{0}}); starT=star(T,P); R=rays starT; assert(rank source R == 3); assert(dim starT== 1); R=QQ[x,y,z,w]; I=ideal(x+y+z+w); T=tropicalVariety(I); P=convexHull(matrix{{0},{0},{0},{0}}, matrix{{1},{0},{0},{0}}, matrix{{1},{1},{1},{1}}); starT=star(T,P); assert(dim starT== 1); /// end restart uninstallPackage "Tropical" installPackage "Tropical" check "Tropical"