From 6296822e890933246fa643f8f294e31ebe6db125 Mon Sep 17 00:00:00 2001 From: Doug Torrance Date: Sun, 1 Sep 2024 20:58:02 -0400 Subject: [PATCH] Remove supplanted-packages directory The current versions of these packages still exist in the main packages directory, and these older versions still exist in the git history. --- .../supplanted-packages/EdgeIdeals.m2 | 4493 ----------- .../packages/supplanted-packages/PieriMaps.m2 | 586 -- .../packages/supplanted-packages/Polyhedra.m2 | 7027 ----------------- 3 files changed, 12106 deletions(-) delete mode 100644 M2/Macaulay2/packages/supplanted-packages/EdgeIdeals.m2 delete mode 100644 M2/Macaulay2/packages/supplanted-packages/PieriMaps.m2 delete mode 100644 M2/Macaulay2/packages/supplanted-packages/Polyhedra.m2 diff --git a/M2/Macaulay2/packages/supplanted-packages/EdgeIdeals.m2 b/M2/Macaulay2/packages/supplanted-packages/EdgeIdeals.m2 deleted file mode 100644 index 1dab9cdcde7..00000000000 --- a/M2/Macaulay2/packages/supplanted-packages/EdgeIdeals.m2 +++ /dev/null @@ -1,4493 +0,0 @@ --- -*- coding: utf-8 -*- - -needsPackage "SimplicialComplexes" - -newPackage("EdgeIdeals", - Version => "0.1", - Date => "July 1, 2008", - Authors => { - {Name => "Chris Francisco", - Email => "chris@math.okstate.edu", - HomePage => "http://www.math.okstate.edu/~chris/" - }, - {Name => "Andrew Hoefel", - Email => "handrew@mathstat.dal.ca", - HomePage => "http://andrew.infinitepigeons.org/" - }, - {Name => "Adam Van Tuyl", - Email => "avantuyl@lakeheadu.ca", - HomePage => "http://flash.lakeheadu.ca/~avantuyl/" - } - }, - Headline => "a package for edge ideals." - ) - -needsPackage "GenericInitialIdeal" -needsPackage "SimplicialComplexes" - -export {HyperGraph, - hyperGraph, - Graph, - graph, - adjacencyMatrix, - allOddHoles, - allEvenHoles, - antiCycle, - changeRing, - chromaticNumber, - cliqueComplex, - cliqueNumber, - coverIdeal, - complementGraph, - completeGraph, - completeMultiPartite, - connectedComponents, - cycle, - degreeVertex, - deleteEdges, - edgeIdeal, - edges, - getCliques, - getEdge, - getEdgeIndex, - getGoodLeaf, - getGoodLeafIndex, - getMaxCliques, - hasGoodLeaf, - hasOddHole, - hyperGraphToSimplicialComplex, - incidenceMatrix, - independenceComplex, - independenceNumber, - inducedHyperGraph, - isBipartite, - isChordal, - isCM, - isConnected, - isEdge, - isForest, - isGoodLeaf, - isGraph, - isLeaf, - isPerfect, - isSCM, - lineGraph, - neighbors, - numConnectedComponents, - numTriangles, - randomGraph, - randomUniformHyperGraph, - randomHyperGraph, - simplicialComplexToHyperGraph, - smallestCycleSize, - spanningTree, - vertexCoverNumber, - vertexCovers, - vertices, - Gins, - BranchLimit, - TimeLimit, - MaximalEdges, - OriginalRing - }; - ----------------------------------------------------------------------------------------- --- --- TYPES --- ----------------------------------------------------------------------------------------- - ----------------------------------------------------------------------------------------- --- HyperGraph ----------------------------------------------------------------------------------------- - -HyperGraph = new Type of HashTable; -hyperGraph = method(TypicalValue => HyperGraph); - -hyperGraph (PolynomialRing, List) := HyperGraph => (R, E) -> ( - -- Output: HyperGraph over R with edges E - -- Assert: R is a polynomial ring - -- Assert: E is a List of Lists of variables of R or - -- E is a List of square-free monomials in R - if any(E, e -> class e =!= List) and any(E, e -> class class e =!= PolynomialRing) - then ( print apply(E, e -> class e) ;error "Edges must be lists of variables or monomials."); - - V := gens R; - --- check needed for square free - if any(E, e-> class class e === PolynomialRing) then E = apply(E, support); - E = apply(E, unique); --- Enforces square-free if edges are given as lists - H := new HyperGraph from hashTable({"ring" => R, "vertices" => V, "edges" => E}); - if any(H#"edges", e -> not instance(e, List)) then error "Edges must be lists."; - if any(H#"edges", e -> not isSubset(e,H#"vertices")) then error "Edges must be subsets of the vertices."; - if any(0..#(H#"edges") -1, I -> - any(0..I-1, J-> isSubset(H#"edges"#I, H#"edges"#J) or isSubset(H#"edges"#J, H#"edges"#I)) - ) - then error "Edges satisfy a inclusion relation"; - return H; -) - -hyperGraph (MonomialIdeal) := HyperGraph => (I) -> -( - if not isSquareFree I then error "Ideals must be square-free."; - hyperGraph(ring I, apply(flatten entries gens I, support)) -) - -hyperGraph (Ideal) := HyperGraph => (I) -> -( - hyperGraph monomialIdeal I -) - -hyperGraph (List) := HyperGraph => (E) -> -( - M := null; - if all(E, e-> class e === List) then ( - if E == {} or E == {{}} then error "Use alternate construction with PolynomialRing to input empty hyperGraph" else - M = monomialIdeal apply(E, product); - ); - if all(E, e-> class class e === PolynomialRing) then M = monomialIdeal E; - if M === null then error "Edge must be represented by a list or a monomial."; - if #E =!= numgens M then error "Edges satisfy an inclusion relation."; - hyperGraph M -) - - ----------------------------------------------------------------------------- --- Graph ----------------------------------------------------------------------------- - -Graph = new Type of HyperGraph; - -graph = method(TypicalValue => Graph); - -graph (PolynomialRing, List) := Graph => (R, E) -> -( - H := hyperGraph(R, E); - if not isGraph(H) then error "Edges must be of size two."; - new Graph from H -) - -graph (MonomialIdeal) := Graph => (I) -> -( - H := hyperGraph(I); - if not isGraph(H) then error "Ideal must have quadratic generators."; - new Graph from H -) - -graph (Ideal) := Graph => (I) -> -( - H := hyperGraph(I); - if not isGraph(H) then error "Ideal must have quadratic generators."; - new Graph from H -) - -graph List := Graph => E -> -( - if E == {} or E == {{}} then error "Use alternate construction with PolynomialRing to input empty graph"; - H := hyperGraph(E); - if not isGraph(H) then error "Edges must be of size two."; - new Graph from H -) - -graph (HyperGraph) := Graph => (H) -> -( - if not isGraph(H) then error "Edges must be of size two."; - new Graph from H -) - -hyperGraph (Graph) := HyperGraph => (G) -> -( - new HyperGraph from G -) - - -------------------------------------------------------------------- --- --- FUNCTIONS --- ------------------------------------------------------------------- - - - - --------------------------------------------------------------- --- Mathematical equality --- return true if two graphs are equal (defined over same ring, --- have same edge sets in some order). --------------------------------------------------------------- - -HyperGraph == HyperGraph := (G,H) -> ( - G#"ring" === H#"ring" and - set(G#"vertices") === set(H#"vertices") and - set(apply(G#"edges", set)) === set(apply(H#"edges",set)) - ) - --------------------------------------------------------------- --- adjacencyMatrix --- return the adjacency matrix of a graph --------------------------------------------------------------- - -adjacencyMatrix = method(); - -adjacencyMatrix Graph := G -> ( - vert:= G#"vertices"; - n := #vert; - m := toList apply(0..n-1,i-> toList apply(0..n-1,j-> if isEdge(G,{vert_i,vert_j}) then 1 else 0)); - return (matrix m) - ) - - ------------------------------------------------------------- --- allEvenHoles --- returns a list of even induced cycles --- NOTE: this function will be SLOWWW! ------------------------------------------------------------ - -allEvenHoles = method(); -allEvenHoles Graph := G -> ( - R := G#"ring"; - S := (coefficientRing R)[append(gens R,newVar)]; - edges := G#"edges"; - numEdges := #edges; - count := 0; - evenCycles := {}; - while count < numEdges do ( - newEdges := {{first(edges#count),newVar},{newVar,(edges#count)#1}}; - tempEdges := apply(join(drop(edges,{count,count}),newEdges),i->apply(i,j->substitute(j,S))); - tempGraph := graph(S,tempEdges); - evenCycles = append(evenCycles,select(allOddHoles tempGraph,i->member(newVar,i))); - count = count+1; - ); - use R; - apply(unique apply(flatten evenCycles,i->select(i,j->(j != newVar))),k->apply(k,l->substitute(l,R))) - ) - --------------------------------------------------------------- --- allOddHoles --- returns a list of all the odd holes in a graph --------------------------------------------------------------- - -allOddHoles = method(); -allOddHoles Graph := G -> ( - coverI := coverIdeal G; - apply(select(ass coverI^2,i->codim i > 3),j->flatten entries gens j) - ) - - -------------------------------------------------------------------- --- antiCycle --- return the complement of a cycle. ------------------------------------------------------------------- - -antiCycle = method(TypicalValue=>Graph); -antiCycle (Ring) := Graph =>(R) -> antiCycle(generators R) - -antiCycle (Ring, ZZ) := Graph =>(R, N) -> antiCycle(apply(N, i->R_i)) - -antiCycle (List) := Graph =>(L)-> ( - if #L < 3 then error "Cannot construct anticycles of length less than three"; - antiCycleEdgeSet := subsets(L,2) - set append(apply(#L-1, i-> {L#i,L#(i+1)}), {(first L),(last L)}); - graph(ring L#0,toList antiCycleEdgeSet) - ) - - ------------------------------------------------------------- --- changeRing --- moves a HyperGraph into a new Ring ------------------------------------------------------------ - -changeRing = method(Options=>{MaximalEdges=>false}) -changeRing (HyperGraph, PolynomialRing, List) := option -> (H, R, L) -> ( - E := edges H; - f := map(R, ring H, L); - E = toList set apply(E, e-> set apply(e, v-> f v)); - I := if option.MaximalEdges then ( - select(toList(0..#E-1), i-> all(toList(0..#E-1), j-> j===i or not isSubset(E_i,E_j))) - ) else ( - select(toList(0..#E-1), i-> all(toList(0..#E-1), j-> j===i or not isSubset(E_j,E_i))) - ) ; - hyperGraph(R,apply(I, i->toList E_i)) - ); - ---------------------------------------------------------------- --- chromaticNumber --- returns the chromatic number of a (hyper)graph --- NOTE: based upon work in progress by Francisco-Ha-Van Tuyl ---------------------------------------------------------------- - -chromaticNumber = method(); -chromaticNumber HyperGraph := H -> ( - Chi := 2; -- assumes graph has at least one edge - m := product H#"vertices"; - j := coverIdeal H; - while ((m^(Chi-1) % j^Chi) != 0) do ( - Chi = Chi + 1; - ); - return (Chi); - ) - - ---------------------------------------------------------------- --- cliqueComplex --- return the simplicial complex whose faces are the cliques of a graph ---------------------------------------------------------------- -cliqueComplex = method(); -cliqueComplex Graph := G -> independenceComplex complementGraph G; - - -------------------------------------------------- --- cliqueNumber --- return the clique number of a graph ------------------------------------------------- - -cliqueNumber = method(); -cliqueNumber Graph := G -> ( - #(last getCliques G) - ) - - ---------------------------------------------------------------- --- complementGraph --- returns the complement of a graph or hypergraph --- NOTE: does something different for graphs vs hypergraphs --------------------------------------------------------------- - -complementGraph = method(); -complementGraph Graph := G -> ( - v := G#"vertices"; - alledges := set(subsets(v,2)); - gedges := set G#"edges"; - gcedges := alledges - gedges; -- edges of the complement - return(graph(G#"ring",toList gcedges)); - ) - -complementGraph HyperGraph := H -> ( - hcedge := apply(H#"edges",e-> toList (set(H#"vertices") - set e)); -- create edge set of hypergraph - return (hyperGraph(H#"ring",toList hcedge)); - ) - - - - ----------------------------------------------------------------------- --- completeGraph --- return graph of complete n-graph ----------------------------------------------------------------------- - -completeGraph = method(); -completeGraph (Ring) := Graph =>(R) -> completeGraph(generators R) - -completeGraph (Ring, ZZ) := Graph =>(R, N) -> completeGraph(apply(N, i->R_i)) - -completeGraph (List) := Graph =>(L)-> ( - if #L === 0 then error "Cannot construct complete graph on no vertices"; - E := for i from 0 to #L -2 list - for j from i+1 to #L-1 list - L#i * L# j; - graph(ring first L, flatten E) - ) - - --------------------------------------------------------------------------- --- completeMultiPartite --- return the complete multi-partite graph --------------------------------------------------------------------------- - -completeMultiPartite = method(); - -completeMultiPartite (Ring, ZZ, ZZ) := Graph =>(R,N,M) -> - completeMultiPartite(R, toList apply(N, i->M)) - -completeMultiPartite (Ring, List) := Graph =>(R, L) -> ( - if all(L, l -> class l === ZZ) then ( - if sum L > #gens(R) then - error "Too few variables in ring to make complete multipartite graph"; - N := 0; - L = for i from 0 to #L-1 list ( - E := toList apply(L#i, j -> R_(j+N)); - N = N+L#i; - E - ); - ); - if all(L, l -> class l === List) then ( - K := flatten for i from 0 to #L-2 list - flatten for j from i+1 to #L-1 list - flatten for x in L#i list - for y in L#j list {x,y}; - return graph(R, K); - ) else error "completeMultipartite must be passed a list of partition sizes or a list of partitions."; - ) - - ------------------------------------------------------------------------ --- connectedComponents --- returns all the connected components of a graph ----------------------------------------------------------------------- - -connectedComponents = method(); -connectedComponents HyperGraph := H -> ( - V := select(H#"vertices", v-> any(H#"edges", e -> member(v,e))); - while #V > 0 list ( - C := {V#0}; - i := 0; - while i < #C do ( - N := select(neighbors(H, C#i), v-> not member(v,C)); - C = join(C,N); - i = i+1; - ); - V = select(V, v -> not member(v,C)); - C - ) - ) - - - ----------------------------------------------------------------------- --- coverIdeal --- return the Alexander dual of edge ideal, otherwise known as the cover ideal ------------------------------------------------------------------------- -coverIdeal = method(); -coverIdeal HyperGraph := H -> dual edgeIdeal H - - - - ----------------------------------------------------------------------------- --- cycle --- return graph of the cycle on n vertices ---------------------------------------------------------------------------- - -cycle = method(TypicalValue=>Graph); -cycle (Ring) := Graph =>(R) -> cycle(generators R) - -cycle (Ring, ZZ) := Graph =>(R, N) -> cycle(apply(N, i->R_i)) - -cycle (List) := Graph =>(L)-> ( - if #L < 3 then error "Cannot construct cycles of length less than three"; - graph(ring L#0,append(apply(#L-1, i-> L#i*L#(i+1)), (last L)*(first L))) - ) - - ----------------------------------------------------------------------- --- degreeVertex --- returns the degree of a vertex ----------------------------------------------------------------------- - -degreeVertex = method(); -degreeVertex (HyperGraph, ZZ) := (H,N) -> ( - degreeVertex(H, (H#"ring")_N) - ) -degreeVertex (HyperGraph, RingElement) := (H,V) -> ( - use H#"ring"; - N := index V; - if N === null then error "Variable is not a vertex of the given HyperGraph"; - number(H#"edges", E-> member(V,E)) - ) - ----------------------------------------------------------------------------------- --- deleteEdges --- remove edges from a (hyper)graph ----------------------------------------------------------------------------------- -deleteEdges = method(); - -deleteEdges (HyperGraph,List) := (H,E) -> ( - if all(E, e -> class class e === PolynomialRing) then E = apply(E, support); - if (isSubset(set E,set H#"edges") =!= true) then error "Second argument must be a subset of the edges, entered as a list"; - hyperGraph(ring H, toList(set(H#"edges")-set(E))) - ) - ---deleteEdges (Graph,List) := (H,E) -> (graph deleteEdges (hyperGraph(H),E)) - - ----------------------------------------------------------------------- --- edgeIdeal --- return the edge ideal of a graph or hypergraph ----------------------------------------------------------------------- - -edgeIdeal = method(); -edgeIdeal HyperGraph := H -> ( - if H#"edges" == {} or H#"edges" == {{}} then return monomialIdeal(0_(H#"ring")); - monomialIdeal apply(H#"edges",product)) - - ------------------------------------------------------------- --- edges --- returns edges of a (hyper)graph ------------------------------------------------------------- - -edges = method(); -edges HyperGraph := H -> H#"edges"; - - ----------------------------------------------------------------- --- getCliques --- return all cliques of the graph ----------------------------------------------------------------- - -getCliques = method(); -getCliques (Graph,ZZ) := (G,d) -> ( - subs := apply(subsets(G#"vertices",d),i->subsets(i,2)); - cliqueIdeals := apply(subs,i->ideal apply(i,j->product j)); - edgeId := edgeIdeal G; - apply(select(cliqueIdeals,i->isSubset(i,edgeId)),j->support j) - ) - -getCliques Graph := G -> ( - numVerts := #(G#"vertices"); - cliques := {}; - count := 2; - while count <= numVerts do ( - newCliques:=getCliques(G,count); - if newCliques == {} then return flatten cliques; - cliques = append(cliques,newCliques); - count = count+1; - ); - flatten cliques - ) - - ------------------------------------------------------------- --- getEdge --- return a specific edge ------------------------------------------------------------- - -getEdge = method(); -getEdge (HyperGraph, ZZ) := (H,N) -> H#"edges"#N; - ------------------------------------------------------------- --- getEdgeIndex --- returns position of a given edge in a list of edges ------------------------------------------------------------- - -getEdgeIndex = method(); -getEdgeIndex (HyperGraph, List) := (H,E) -> ( - if class class E === PolynomialRing then E = support E; - N := select(0..#(H#"edges")-1, N -> set H#"edges"#N === set E); - if #N === 0 then return -1; - return first N; -) - -getEdgeIndex (HyperGraph, RingElement) := (H,E) -> ( - getEdgeIndex(H, support E) -) - ------------------------------------------------------------ --- getGoodLeaf --- return a "Good Leaf" of a hypergraph ----------------------------------------------------------- - -getGoodLeaf = method(); -getGoodLeaf HyperGraph := H -> ( - return H#"edges"#(getGoodLeafIndex H); -) - - ------------------------------------------------------------- --- getGoodLeafIndex --- return the index of a "Good Leaf" in a hypergraph ------------------------------------------------------------- - -getGoodLeafIndex = method(); -getGoodLeafIndex HyperGraph := H -> -( GL := select(0..#(H#"edges")-1, N -> isGoodLeaf(H,N)); - if #GL == 0 then return -1; - return first GL; -); - --------------------------------------------------------------------------- --- getMaxCliques --- return all cliques of maximal size --------------------------------------------------------------------------- - - -- return all cliques of maximal size -getMaxCliques = method(); -getMaxCliques Graph := G -> ( - cliqueList := getCliques G; - clNum := #(last cliqueList); - select(cliqueList,i->#i == clNum) - ) - - ------------------------------------------------------------------------------ --- hasGoodLeaf --- checks if a hypergraph has any "Good Leaves" ----------------------------------------------------------------------------- - -hasGoodLeaf = method(); -hasGoodLeaf HyperGraph := H -> any(0..#(H#"edges")-1, N -> isGoodLeaf(H,N)) - - ------------------------------------------------------------------------------- --- hasOddHole --- checks if a graph has an odd hole (not triangle) ------------------------------------------------------------------------------ - -hasOddHole = method(); -hasOddHole Graph := G -> ( - coverI := coverIdeal G; - any(ass coverI^2,i->codim i > 3) - ) - --------------------------------------------------- --- hyperGraphToSimplicialComplex --- change the type of a (hyper)graph to a simplicial complex ---------------------------------------------------- -hyperGraphToSimplicialComplex = method() -hyperGraphToSimplicialComplex HyperGraph := H -> ( - simplicialComplex flatten entries gens edgeIdeal H - ) - - - - ------------------------------------------------------------------------------ --- incidenceMatrix --- return the incidence matrix of a graph ------------------------------------------------------------------------------ - -incidenceMatrix = method(); - -incidenceMatrix HyperGraph := H -> ( - v:= H#"vertices"; - e := H#"edges"; - m := toList apply(0..#v-1,i-> toList apply(0..#e-1,j-> if member(v_i,e_j) then 1 else 0)); - return (matrix m) - ) - - -------------------------------------------------------------------------------- --- independenceComplex --- returns the simplicial complex whose faces are the independent sets of a (hyper)graph --------------------------------------------------------------------------------- -independenceComplex = method(); - -independenceComplex HyperGraph := H -> (simplicialComplex edgeIdeal H) - - ------------------------------------------------------------------- --- independenceNumber --- return the independence number, the size of the largest independent set of a vertices ------------------------------------------------------------------- - -independenceNumber = method(); -independenceNumber Graph:= G -> ( - return (dim edgeIdeal G); - ) - - --------------------------------------------------------------------------------- --- inducedHyperGraph --- given a set of vertices, return induced graph on those vertices --------------------------------------------------------------------------------- ---if OriginalRing is true, then the hypergraph stays in the larger ring. ---by default, the ring of the induced hypergraph is the smaller ring. ---this avoids having lots of isolated vertices in the resulting hypergraph. - -inducedHyperGraph = method(Options=>{OriginalRing=>false}); -inducedHyperGraph (HyperGraph,List) := opts -> (H,S) -> ( - if (isSubset(set S, set H#"vertices") =!= true) then error "Second argument must be a subset of the vertices"; - ie := select(H#"edges",e -> isSubset(set e,set S)); - if not opts#OriginalRing then ( - R := (coefficientRing H#"ring")[S]; - F := map(R,H#"ring"); - ienew := apply(ie,e->apply(e,v->F(v))); - use H#"ring"; - return(hyperGraph(R,ienew)); - ); - return(hyperGraph(ring H,ie)); - ) - - ------------------------------------------------------------ --- isBipartite --- checks if a graph is bipartite ------------------------------------------------------------ - -isBipartite = method(); -isBipartite Graph := G -> (chromaticNumber G == 2); -- checks if chromatic number is 2 - - -------------------------------------------------------------- --- isChordal --- check if a graph is a chordal graph -------------------------------------------------------------- - -isChordal = method(); -- based upon Froberg's characterization of chordal graphs -isChordal Graph := G -> ( - I := edgeIdeal complementGraph G; - graphR := G#"ring"; - if I == ideal(0_graphR) then return (true); - D := min flatten degrees I; - B := coker gens I; - R := regularity(B); - if D-1 =!= R then return (false); - return(true); - ) - -------------------------------------------------------------- --- isCM --- checks if a (hyper)graph is Cohen-Macaulay ------------------------------------------------------------- - -isCM = method(); - -isCM HyperGraph := H -> ( - I := edgeIdeal H; - codim I == pdim coker gens I - ) - --- R := H#"ring"; --- M := R^1 / edgeIdeal H; --- Q := R^1 / ideal gens R; --- D := dim M; --- Ext^D(Q,M) !=0 and Ext^(D-1)(Q,M) == 0 --- ) - ------------------------------------------------------------- --- isConnected --- checks if a graph is connected --- (the graph is connected <=> A, the adjacency the matrix, --- and I, the identity matrix of size n, has the --- property that (A+I)^{n-1} has no zero entries) ------------------------------------------------------------- - -isConnected = method(); -isConnected HyperGraph := H -> numConnectedComponents H == 1 - - ------------------------------------------------------------- --- isEdge --- checks if a set is an edge of a (hyper)graph ------------------------------------------------------------- - -isEdge = method(); -isEdge (HyperGraph, List) := (H,E) -> ( - if class class E === PolynomialRing then E = support E; - any(H#"edges", G->set G === set E) - ) -isEdge (HyperGraph, RingElement) := (H,E) -> ( - isEdge(H, support E) - ) - -------------------------------------------------------------- --- isForest --- checks if a (hyper)graph is a tree ------------------------------------------------------------- - -isForest = method(); -isForest Graph := G -> (smallestCycleSize G == 0); - -isForest HyperGraph := H -> ( - E := toList(0..#(H#"edges") -1); - while #E =!= 0 do ( - L := select(E, i-> isGoodLeaf(H,i)); - if #L === 0 then return false; - H = hyperGraph(H#"ring", drop(H#"edges", {first L, first L})); - E = toList(0..#(H#"edges") -1); - ); - true - ) - -------------------------------------------------------------- --- isGoodLeaf --- checks if the n-th edge of a hypergraph is a "Good Leaf" ----------------------------------------------------------- - -isGoodLeaf = method(); -isGoodLeaf (HyperGraph, ZZ) := (H,N) -> ( - intersectEdges := (A,B) -> set H#"edges"#A * set H#"edges"#B; - overlaps := apply(select(0..#(H#"edges")-1, M -> M =!= N), M -> intersectEdges(M,N)); - overlaps = sort toList overlaps; - --Check if the overlaps are totally ordered - all(1..(#overlaps -1), I -> overlaps#(I-1) <= overlaps#I) - ); - ------------------------------------------------------------- --- isGraph --- checks if a hypergraph is a graph ------------------------------------------------------------- - -isGraph = method(); -isGraph HyperGraph := Boolean => (H) -> ( - H#"edges" == {{}} or H#"edges" == {} or all(H#"edges", e-> #e === 2 ) - ) - - --------------------------------------------------------------- --- isLeaf --- checks if the n-th edge of the (hyper)graph is a leaf --------------------------------------------------------------- - -isLeaf = method(); -isLeaf (HyperGraph, ZZ) := (H,N) -> ( - intersectEdges := (A,B) -> set H#"edges"#A * set H#"edges"#B; - overlaps := apply(select(0..(#(H#"edges")-1), M -> M =!= N), M -> intersectEdges(M,N)); - overlapUnion := sum toList overlaps; - any(overlaps, branch -> isSubset(overlapUnion,branch)) - ) - -isLeaf (Graph, ZZ) := (G,N) -> ( - any(G#"edges"#N, V -> degreeVertex(G,V) === 1) - ---Note N refers to an edge index - ) - -isLeaf (HyperGraph, RingElement) := (H,V) -> ( - E := select(0..#(H#"edges")-1, I -> member(V, H#"edges"#I)); - #E == 1 and isLeaf(H, E#0) - ) - - ------------------------------------------------------------- --- isPerfect --- checks if a graph is a perfect graph ------------------------------------------------------------- - -isPerfect = method(); -isPerfect Graph := G -> ( - if hasOddHole G then return false; - if hasOddHole complementGraph G then return false; - return true; - ) - ------------------------------------------------------------- --- isSCM --- checks if (hyper)graph is Sequentially Cohen-Macaulay -------------------------------------------------------------- ---uses GenericInitialIdeals package for the gin ---if the user selects the Gins option - -isSCM= method(Options=>{Gins=>false}); -isSCM HyperGraph := opts -> H -> ( - J := dual edgeIdeal H; - if opts#Gins then ( - g := gin J; - return (#(flatten entries mingens g) == #(flatten entries mingens J)); - ); - degs := sort unique apply(flatten entries gens J,i->first degree i); - numDegs := #degs; - count := 0; - while count < numDegs do ( - Jdeg:=monomialIdeal super basis(degs#count,J); - if regularity Jdeg != degs#count then return false; - count = count+1; - ); - return true; - ) - - ------------------------------------------------------------------- --- lineGraph --- return the graph with E(G) as its vertices where two --- vertices are adjacent when their associated edges are adjacent in G. ------------------------------------------------------------------- - -lineGraph = method(); - -lineGraph HyperGraph := H -> ( - R := QQ[x_0..x_(#edges(H)-1)]; - E := apply(H#"edges", set); - L := select(subsets(numgens R, 2), e -> #(E#(e#0) * E#(e#1)) > 0); - graph(R, apply(L,e->apply(e, i-> x_i))) - ) - - ------------------------------------------------------------ --- neighbors --- returns all the neighbors of a vertex or a set ------------------------------------------------------------ - -neighbors = method(); - -neighbors (HyperGraph, ZZ) := (H, N) -> neighbors(H, H#"ring"_N) - -neighbors (HyperGraph, RingElement) := (H,V) -> ( - unique select(flatten select(H#"edges", E-> member(V,E)), U-> U =!= V) - ) - -neighbors (HyperGraph, List) := (H,L) -> ( - if any(L, N-> class N === ZZ) then L = apply(L, N-> H#"ring"_N); - unique select(flatten apply(L, V-> neighbors(H,V)), U -> not member(U, L)) - ) - ------------------------------------------------------------- --- numConnectedComponents --- the number of connected components of a (hyper)Graph ------------------------------------------------------------- - -numConnectedComponents = method(); -numConnectedComponents HyperGraph:= H -> (rank HH_0 hyperGraphToSimplicialComplex H)+1 - ------------------------------------------------------------ --- numTrianges --- returns the number of triangles in a graph ------------------------------------------------------------ - -numTriangles = method(); -numTriangles Graph := G -> ( - number(ass (coverIdeal G)^2,i->codim i==3) - ) - ------------------------------------------------------------ --- randomGraph --- returns a graph with a given vertex set and randomly chosen --- edges with the user determining the number of edges ------------------------------------------------------------ -randomGraph = method(); -randomGraph (PolynomialRing,ZZ) := (R,num) -> ( - graph randomUniformHyperGraph(R,2,num) - ) - ------------------------------------------------------------ --- randomUniformHyperGraph --- returns a random hypergraph on a given vertex set --- user chooses cardinality of edges and the number of edges ------------------------------------------------------------ - -randomUniformHyperGraph = method(); -randomUniformHyperGraph (PolynomialRing,ZZ,ZZ) := (R,card,num) -> ( - if card <= 0 then error "cardinalities of hypergraphs must be positive integers"; - if num < 0 then error "number of edges must be nonnegative"; - if num > binomial(numgens R,card) then error "can't make that many edges"; - edges := take(random subsets(gens R,card),num); - hyperGraph(R,edges) - ) - ------------------------------------------------------------ --- randomHyperGraph --- returns a random hypergraph on a given vertex set --- user chooses the size of each edge ------------------------------------------------------------ -recursiveRandomHyperGraph = (V,L,D,BranchLimit,TerminateTime) -> ( - if #D === 0 then return L; - V = random V; - W := set take(V, D#0); - if any(L, l -> all(W, w-> member(w#0,l))) then return null; - if any(L, l -> all(l, w-> member(w#0,W))) then return null; - L = append(L, W); - D = drop(D,1); - H := recursiveRandomHyperGraph(V,L,D,BranchLimit,TerminateTime); - I := 0; - while H === null and I < BranchLimit + #D and currentTime() < TerminateTime do ( - H = recursiveRandomHyperGraph(V,L,D,BranchLimit,TerminateTime); - I = I - 1; - ); - return H; -) - -randomHyperGraph = method(Options => {TimeLimit => 5, BranchLimit => 3}); -randomHyperGraph (PolynomialRing,List) := opts -> (R,D) -> ( - if any(D, d-> d < 0) then error "edge sizes must be nonnegative"; - if sum(apply(toList(0..#D-1), i-> (binomial(numgens R, D_i))^(-1))) > 1 then return null; - V := gens R; - if opts.TimeLimit === 0 then opts.TimeLimit === 24*60*60; - TerminateTime := currentTime() + opts.TimeLimit; - H := null; - i := 0; - while H === null and i < opts.BranchLimit + #D and currentTime() < TerminateTime do ( - H = recursiveRandomHyperGraph(V,{},D,opts.BranchLimit,TerminateTime); - i = i+1; - ); - if H === null then return null; - return hyperGraph(R, apply(H, h-> toList h)); - ) - ------------------------------------------------------------ --- ring --- returns the ring of a hypergraph ------------------------------------------------------------ - -ring HyperGraph := H -> H#"ring" - --------------------------------------------------- --- simplicialComplexToHyperGraph --- change the type of a simplicial complex to a (hyper)graph ---------------------------------------------------- - -simplicialComplexToHyperGraph = method() - -simplicialComplexToHyperGraph SimplicialComplex := D -> ( - hyperGraph facets D - ) - ------------------------------------------------------- --- smallestCycleSize --- length of smallest induced cycle in a graph -------------------------------------------------------- -smallestCycleSize = method(); - -smallestCycleSize Graph := G -> ( - if numTriangles G =!= 0 then return(3); - R := res edgeIdeal complementGraph G; - smallestCycle := 0; - i := 1; - -- this loop determines if there is a non-linear syzygy - -- the first non-linear syzygy tells us the smallest induced - -- cycle has length >= 4. This is based upon - -- the paper of Eisenbud-Green-Hulek-Popescu, - -- "Restricting linear syzygies: algebra and geometry" - while ((smallestCycle == 0) and (i <= pdim betti R)) do ( - A := R_i; - B := flatten degrees A ; - t := tally B; - if (t #? (i+1)) then ( - d := rank A; - if d == t#(i+1) then i = i+1 else smallestCycle = i+2; - ) - else smallestCycle = i+2; - ); - -- If the resolution is linear, smallestCycle still has the value of 0 - -- Because the resolution is linear, the graph is chordal, by - -- a result of Froberg. Since we have taken care of the case - -- that G has a triangle, the graph will be a tree. - return (smallestCycle); - ); - - - ------------------------------------------------------------- --- spanningTree --- returns a spanning tree of a graph ------------------------------------------------------------ - -spanningTree = method(); -spanningTree Graph:= G-> ( - if #edges(G) === 0 then return G; - E := G#"edges"; - W := set(G#"vertices"); -- vertices not visited yet - V := {}; -- vertices visited - T := {}; -- edges in tree - M := 0; -- index of vertex to visit next - while #W > 0 do ( - X := first toList W; - W = W - set{X}; - V = append(V,X); - while M < #V do ( - L := select(E, e-> member(V#M,e) and not member(first toList(set(e)-set{V#M}), V)); - T = T | L; - L = toList(set(flatten L) - set{V#M}); - V = V | L; - W = W - set(L); - M = M + 1; - ); - ); - return graph T; - ); - - ----------------------------------------------------- --- vertexCoverNumber --- return the vertex cover number of a (hyper)graph ---------------------------------------------------- - -vertexCoverNumber = method(); -vertexCoverNumber HyperGraph := H -> ( - min apply(flatten entries gens coverIdeal H,i->first degree i) - ) - ----------------------------------------- --- vertexCovers --- return all minimal vertex covers --- (these are the generators of the Alexander dual of the edge ideal) ----------------------------------------- - -vertexCovers = method(); -vertexCovers HyperGraph := H -> ( - flatten entries gens coverIdeal H - ) - ------------------------------------------ --- vertices --- returns the vertices of the (hyper)graph --------------------------------------------- - -vertices = method(); -vertices HyperGraph := H -> H#"vertices"; - -beginDocumentation() - ---------------------------------------------------------- ---------------------------------------------------------- --- Simple Doc information ---------------------------------------------------------- ---------------------------------------------------------- - ---******************************************************* --- DOCUMENTATION FOR PACKAGE ---******************************************************* - -doc /// - Key - EdgeIdeals - Headline - A package for working with the edge ideals of (hyper)graphs - Description - Text - {\em EdgeIdeals} is a package to work with the edge ideals of (hyper)graphs. - - An edge ideal is a square-free monomial ideal where the generators of the monomial ideal correspond to the edges - of the (hyper)graph. An edge ideal complements the Stanley-Reisner correspondence - (see @TO SimplicialComplexes @) by providing an alternative combinatorial interpretation of the - monomial generators. - - This package exploits the correspondence between square-free monomial ideals and the combinatorial - objects, by using commutative algebra routines to derive information about (hyper)graphs. - For some of the mathematical background on this material, see Chapter 6 of the textbook - {\it Monomial Algebras} by R. Villarreal and the survey paper - of T. Ha and A. Van Tuyl ("Resolutions of square-free monomial ideals via facet ideals: a survey," - Contemporary Mathematics. 448 (2007) 91-117). - - - {\bf Note:} When we use the term "edge ideal of a hypergraph", we are actually referring to - the edge ideal of a clutter, a hypergraph where no edge is a subset of another edge. - If $H$ is a hypergraph that is not a clutter, then when we form its edge ideal - in a similar fashion, some information will be lost because not all of the edges of the - hypergraph will correspond to minimal generators, so we require that the edges of hypergraphs - do not satisfy any inclusion relations. The edge ideal of a hypergraph is similar to the facet - ideal of a simplicial complex, as defined by S. Faridi in "The facet ideal of a simplicial complex," - Manuscripta Mathematica 109, 159-174 (2002). -/// - -document { - Key => "Constructor Overview", - Headline => "a summary of the many ways of making graphs and hypergraphs", - PARA { "The following is separated into four sections:"}, - UL {"Basic Constructors", "Converting Types", "Special Graphs", "Random (Hyper)Graphs"}, - SUBSECTION "Basic Constructors", - PARA { - "The main way of constructing ", TO "Graph", " and " , TO "HyperGraph", " objects is to use the ", - TO "graph", " and ", TO "hyperGraph", " methods. These methods are overridden to provide many ways ", - "of specifying edges." }, - PARA { "For the purposes of the EdgeIdeals package, every graph and hypergraph is associated to a ring ", - "whose variables correspond to the vertices of the (hyper)graph. Thus, the most explicit way to ", - "make a graph or hypergraph is by ", TO (graph, PolynomialRing, List), " and ", TO (hyperGraph, PolynomialRing, List), ".", - "The list parameter must contain edges which themselves are lists of variables in the ring."}, - EXAMPLE {"R = QQ[x,y,z,w];","G = graph(R, {{x,y},{x,z},{y,z},{x,w}})", "H = hyperGraph(R, {{x,y,z},{x,w}})"}, - PARA { "Probably the most convenient may of specifying edges is as a list of monomial. Using the ", TO (graph, List), " and ", - TO (hyperGraph, List), " methods implicitly defines the ring of the (hyper)graph to be the ring containing the monomials ", - " in the ", TO List, ". The following example gives the same hypergraphs as before."}, - EXAMPLE { "R = QQ[x,y,z,w];", "G = graph {x*y, x*z, y*z, x*w}", "H = hyperGraph {x*y*z, x*w}" }, - PARA { "The ", TO "graph", " and ", TO "hyperGraph", " constructors can also be used to make (hyper)graphs from square-free monomial ideals.", - "The minimal generators of the ideal become the edges of the (hyper)graph. The ideal must be generated by quadratics if the ", TO "graph", - " constructor is used."}, - EXAMPLE "G = graph ideal(x*y, x*z, y*z, x*w)", - SUBSECTION "Converting Types", - PARA { "In this section, we will see how to convert between ", TO SimplicialComplex ,"es and ", TO HyperGraph, - "s, as well as between ", TO Graph, "s and ", TO HyperGraph, "s."}, - PARA { "The methods ", TO simplicialComplexToHyperGraph, " and ", TO hyperGraphToSimplicialComplex, - " accomplish the former conversion in the following way. In ", TO simplicialComplexToHyperGraph, - " facets of the simplicial complex become the edges of the hypergraph, while in ", TO hyperGraphToSimplicialComplex, - " the edges of the hypergraph become the facets of the new simplicial complex." - }, - EXAMPLE { "R = QQ[x,y,z,w];", - "H = hyperGraph {x*y*z,x*w};", - "D = hyperGraphToSimplicialComplex H", - "simplicialComplexToHyperGraph D"}, - PARA { "The conversion of a graph into a hypergraph and vice versa use the constructors ", TO "graph", " and ", TO "hyperGraph", ". ", - "Any graph can be converted to a hyperGraph, but when a hyperGraph is converted into a graph, a check is run to ensure ", - "that the edges are all of size two. An error will be produced if this is not the case."}, - EXAMPLE { "R = QQ[x,y,z,w];", - "G = graph {x*y, x*z, y*z, x*w};", - "H = hyperGraph G", - "graph H"}, - PARA { "Since the ", TO Graph, " type is a subclass of ", TO HyperGraph, ", any method that takes a ", TO HyperGraph, - " will also work on ", TO Graph, "s. So the conversion from graph to hypergraph is seldom needed; it is ", - "only needed when a method works differently on graphs than on hypergraphs (see ", TO complementGraph, " for an example)."}, - PARA { "On the other hand, the conversion from hypergraph to graph is very important as many methods are only defined on graphs. ", - "In the following example, we use the ", TO isChordal, " method which only applies to graphs and hence necessitates a ", - "conversion of types."}, - EXAMPLE { "R = QQ[x,y,z,w];", - "D = simplicialComplex {x*y, x*z, y*z, x*w};", - "H = simplicialComplexToHyperGraph D", - "G = graph H", - "isChordal G "}, - SUBSECTION "Special Graphs", - PARA { "In addition to the more general constructors, there a number of methods which produce certain special graphs."}, - PARA { EM "Cycles", " can be constructed using ", TO cycle, " which, depending on the parameters, uses all or some of the variables", - " in the ring to define a graph cycle."}, - EXAMPLE { "R = QQ[x,y,z,w];", "cycle R", "cycle(R,3)", "cycle {x,y,w} "}, - PARA { EM "Anti-Cycles", ", the graph complements cycles, can be constructed using ", TO antiCycle, " which has takes parameters", - " similar to those of ", TO cycle, "."}, - EXAMPLE { "R = QQ[x,y,z,w];", "antiCycle R"}, - PARA { EM "Complete graphs", " can be constructed using ", TO completeGraph, " which defines a graph with every possible edge between", - " a given set a vertices."}, - EXAMPLE { "R = QQ[x,y,z,w];", "completeGraph R", "completeGraph(R,3)", "completeGraph {x,y,w} "}, - PARA { EM "Complete multipartite graphs", " can be constructed using ", TO completeMultiPartite, " which defines a graph with every ", - "possible edge between certain partitions of the vertices. See ", TO completeMultiPartite, " for more details."}, - EXAMPLE { "R = QQ[a,b,x,y];", "completeMultiPartite(R,2,2)"}, - SUBSECTION "Random (Hyper)Graphs", - PARA { "Three methods are provided for the construction of random (hyper)graphs."}, - UL{ TOH randomGraph, TOH randomUniformHyperGraph, TOH randomHyperGraph}, - PARA { "Each method allows you to specify the number of edges desired. For the random hypergraph methods, the sizes of the edges must", - " also be specified."}, - EXAMPLE { "R = QQ[x,y,z,u,v];", - "randomGraph(R,3)", - "randomUniformHyperGraph(R,2,3)", - "randomHyperGraph(R,{3,2,1})"}, - PARA { "The ", TO randomHyperGraph, " method is not guaranteed to return a hypergraph; sometimes it returns null.", - "Please see the documentation of this method for more details."}, - SeeAlso => { Graph, HyperGraph, graph, hyperGraph, simplicialComplexToHyperGraph, hyperGraphToSimplicialComplex, cycle, antiCycle, completeGraph, - completeMultiPartite, randomGraph, randomUniformHyperGraph, randomHyperGraph} -} - ---******************************************************* --- DOCUMENTATION FOR TYPES ---******************************************************* - ---------------------------------------------------------- --- DOCUMENTATION HyperGraph ---------------------------------------------------------- - - -doc /// - Key - HyperGraph - Headline - a class for hypergraphs. - Description - Text - This class represents hypergraph. A hypergraph is a tuple {\tt (V,E)} of vertices {\tt V} and edges {\tt E} - which are subsets of the vertices. In this package, all hypergraphs have the additional property that no edge - is subset of any other edge. Hypergraphs of this form are often referred to as clutters. - Example - R = QQ[w,x,y,z]; - H = hyperGraph(R, {{w,x},{w,y,z},{x,y,z}}); - vertices H - edges H - ring H - Text - Hypergraphs are always associated with a polynomial ring whose variables are the vertices of the hypergraph. - SeeAlso - hyperGraph - Graph - "Constructor Overview" -/// - -doc /// - Key - Graph - Headline - a class for graphs. - Description - Text - This class represents simple graphs. This class extends @TO HyperGraph@ and hence - inherits all HyperGraph methods. - Example - R = QQ[w,x,y,z]; - G = graph(R, {{w,x},{w,y},{w,z},{y,z}}); - vertices G - edges G - ring G - Text - Like hypergraphs, graphs are associated with a polynomial ring whose variables are the vertices of the graph. - SeeAlso - graph - HyperGraph - "Constructor Overview" -/// - - ---------------------------------------------------------- --- DOCUMENTATION hyperGraph ---------------------------------------------------------- - -doc /// - Key - hyperGraph - (hyperGraph, PolynomialRing, List) - (hyperGraph, MonomialIdeal) - (hyperGraph, Ideal) - (hyperGraph, List) - (hyperGraph, Graph) - Headline - constructor for HyperGraph. - Usage - H = hyperGraph(R,E) \n H = hyperGraph(I) \n H = hyperGraph(E) \n H = hyperGraph(G) - Inputs - R:PolynomialRing - whose variables correspond to vertices of the hypergraph. - E:List - contain a list of edges, which themselves are lists of vertices. - I:MonomialIdeal - which must be square-free and whose generators become the edges of the hypergraph. - J:Ideal - which must be square-free monomial and whose generators become the edges of the hypergraph. - G:Graph - which is to be converted to a HyperGraph. - Outputs - H:HyperGraph - Description - Text - The function {\tt hyperGraph} is a constructor for @TO HyperGraph @. The user - can input a hypergraph in a number of different ways, which we describe below. - The information describing the hypergraph is stored in a hash table. We require that - there be no inclusion relations between the edges of a hypergraph; that is, that it - be a clutter. The reason is that this package is designed for edge ideals, which would - lose any information about edges that are supersets of other edges. - - For the first possibility, the user inputs a polynomial ring, which specifies the vertices - of graph, and a list of the edges of the graph. The edges are represented as lists. - Example - R = QQ[a..f] - E = {{a,b,c},{b,c,d},{c,d,e},{e,d,f}} - h = hyperGraph (R,E) - Text - Altenatively, if the polynomial ring has already been defined, it suffices to simply enter - the list of the edges. - Example - S = QQ[z_1..z_8] - E1 = {{z_1,z_2,z_3},{z_2,z_4,z_5,z_6},{z_4,z_7,z_8},{z_5,z_7,z_8}} - E2 = {{z_2,z_3,z_4},{z_4,z_8},{z_7,z_6,z_8},{z_1,z_2}} - h1 = hyperGraph E1 - h2 = hyperGraph E2 - Text - The list of edges could also be entered as a list of square-free monomials. - Example - T = QQ[w,x,y,z] - e = {w*x*y,w*x*z,w*y*z,x*y*z} - h = hyperGraph e - Text - Another option for defining an hypergraph is to use an @TO ideal @ or @TO monomialIdeal @. - Example - C = QQ[p_1..p_6] - i = monomialIdeal (p_1*p_2*p_3,p_3*p_4*p_5,p_3*p_6) - hyperGraph i - j = ideal (p_1*p_2,p_3*p_4*p_5,p_6) - hyperGraph j - Text - Since a graph is specific type of hypergraph, we can change the type - of a graph to hypergraph. - Example - D = QQ[r_1..r_5] - g = graph {r_1*r_2,r_2*r_4,r_3*r_5,r_5*r_4,r_1*r_5} - h = hyperGraph g - Text - Some special care is needed it construct the empty hypergraph, that is, the hypergraph with no - edges. In this case, the input cannot be a list (since the constructor does not - know which ring to use). To define the empty graph, use a polynomial ring and (monomial) ideal. - Example - E = QQ[m,n,o,p] - i = monomialIdeal(0_E) -- the zero element of E (do not use 0) - hyperGraph i - j = ideal (0_E) - hyperGraph j - SeeAlso - graph - "Constructor Overview" -/// - - ---------------------------------------------------------- --- DOCUMENTATION graph ---------------------------------------------------------- - -doc /// - Key - graph - (graph, PolynomialRing, List) - (graph, MonomialIdeal) - (graph, Ideal) - (graph, List) - (graph, HyperGraph) - Headline - constructor for Graph. - Usage - G = graph(R,E) \n G = graph(I) \n G = graph(E) \\ G = graph(H) - Inputs - R:PolynomialRing - whose variables correspond to vertices of the hypergraph. - E:List - contain a list of edges, which themselves are lists of vertices. - I:MonomialIdeal - which must be square-free, quadratic, and whose generators become the edges of the graph. - J:Ideal - which must be square-free, quadratic, monomial and whose generators become the edges of the graph. - H:HyperGraph - which is to be converted to a graph. The edges in {\tt H} must be of size two. - Outputs - G:Graph - Description - Text - The function {\tt graph} is a constructor for @TO Graph @, a type of @TO HyperGraph @. The user - can input a graph in a number of different ways, which we describe below. The information - describing the graph is stored in a hash table. - - For the first possibility, the user inputs a polynomial ring, which specifies the vertices - of graph, and a list of the edges of the graph. The edges are represented as lists. - Example - R = QQ[a..f] - E = {{a,b},{b,c},{c,f},{d,a},{e,c},{b,d}} - g = graph (R,E) - Text - Altenatively, if the polynomial ring has already been defined, it suffices to simply enter - the list of the edges. - Example - S = QQ[z_1..z_8] - E1 = {{z_1,z_2},{z_2,z_3},{z_3,z_4},{z_4,z_5},{z_5,z_6},{z_6,z_7},{z_7,z_8},{z_8,z_1}} - E2 = {{z_1,z_3},{z_3,z_4},{z_5,z_2},{z_2,z_4},{z_7,z_8}} - g1 = graph E1 - g2 = graph E2 - Text - The list of edges could also be entered as a list of square-free quadratic monomials. - Example - T = QQ[w,x,y,z] - e = {w*x,w*y,w*z,x*y,x*z,y*z} - g = graph e - Text - Another option for defining an graph is to use an @TO ideal @ or @TO monomialIdeal @. - Example - C = QQ[p_1..p_6] - i = monomialIdeal (p_1*p_2,p_2*p_3,p_3*p_4,p_3*p_5,p_3*p_6) - graph i - j = ideal (p_1*p_2,p_1*p_3,p_1*p_4,p_1*p_5,p_1*p_6) - graph j - Text - If a hypergraph has been defined that is also a graph, one can change the type of the hypergraph - into a graph. - Example - D = QQ[r_1..r_5] - h = hyperGraph {r_1*r_2,r_2*r_4,r_3*r_5,r_5*r_4,r_1*r_5} - g = graph h - Text - Some special care is needed it construct the empty graph, that is, the graph with no - edges. In this case, the input cannot be a list (since the constructor does not - know which ring to use). To define the empty graph, use a polynomial ring and (monomial) ideal. - Example - E = QQ[m,n,o,p] - i = monomialIdeal(0_E) -- the zero element of E (do not use 0) - graph i - j = ideal (0_E) - graph j - SeeAlso - hyperGraph - "Constructor Overview" -/// - - - ---------------------------------------------------------------------------------------------- - ---********************************************************** --- DOCUMENTATION FOR FUNCTIONS ---********************************************************** - - ------------------------------------------------------------- --- DOCUMENTATION equality == ------------------------------------------------------------- - -doc /// - Key - (symbol ==, HyperGraph, HyperGraph) - Headline - equality - Usage - g == h - Inputs - g:HyperGraph - h:HyperGraph - Outputs - b:Boolean - true if g and h are equal - Description - Text - This function determines if two HyperGraphs are mathematically equal. - Two HyperGraphs are equal if they are defined over the same ring, have - the same variables and have the same set of edges. In particular, - the order of the edges and the order of variables within each edge - does not matter. - Example - R = QQ[a..f]; - g = hyperGraph {{a,b,c},{b,c,d},{d,e,f}}; - h = hyperGraph {{b,c,d},{a,b,c},{f,e,d}}; - k = hyperGraph {{a,b},{b,c,d},{d,e,f}}; - g == h - g == k -/// - ------------------------------------------------------------- --- DOCUMENTATION adjacencyMatrix ------------------------------------------------------------- - -doc /// - Key - adjacencyMatrix - (adjacencyMatrix, Graph) - Headline - returns the adjacency Matrix of a graph - Usage - M = adjacencyMatrix G - Inputs - G:Graph - Outputs - M:Matrix - the adjacency matrix of the graph - Description - Text - This function returns the adjacency matrix of the inputted graph. The (i,j)^{th} position - of the matrix is 1 if there is an edge between the i^{th} vertex and j^{th} vertex, - and 0 otherwise. The rows and columns are indexed by the variables of the ring and uses the - ordering of the variables for determining the order of the rows and columns. - Example - S = QQ[a..f]; - G = graph {a*b,a*c,b*c,c*d,d*e,e*f,f*a,a*d} - t = adjacencyMatrix G - T = QQ[f,e,d,c,b,a]; - G = graph {a*b,a*c,b*c,c*d,d*e,e*f,f*a,a*d} - t = adjacencyMatrix G -- although the same graph, matrix is different since variables have different ordering - SeeAlso - incidenceMatrix - vertices -/// - ------------------------------------------------------------- --- DOCUMENTATION allEvenHoles ------------------------------------------------------------- - -doc /// - Key - allEvenHoles - (allEvenHoles, Graph) - Headline - returns all odd holes in a graph - Usage - L = allEvenHoles G - Inputs - G:Graph - Outputs - L:List - returns all even holes contained in {\tt G}. - Description - Text - The method is based on work of Francisco-Ha-Van Tuyl, looking at the associated primes - of the square of the Alexander dual of the edge ideal. An even hole is an even induced - cycle (necessarily of length at least four). The algorithm for allEvenHoles uses an - observation of Mermin. Fix an edge, and split this edge into two different edges, - introducing a new vertex. Find all the odd holes in that graph. Do that for each edge - in the graph, one at a time, and pick out all the odd holes containing the additional - vertex. Dropping this vertex from each of the odd holes gives all the even holes in - the original graph. - Example - R = QQ[a..f]; - G = cycle(R,6); - allEvenHoles G - H = graph(monomialIdeal(a*b,b*c,c*d,d*e,e*f,a*f,a*d)) --6-cycle with a chord - allEvenHoles H --two 4-cycles - SeeAlso - allOddHoles - hasOddHole -/// - ------------------------------------------------------------- --- DOCUMENTATION allOddHoles ------------------------------------------------------------- - -doc /// - Key - allOddHoles - (allOddHoles, Graph) - Headline - returns all odd holes in a graph - Usage - L = allOddHoles G - Inputs - G:Graph - Outputs - L:List - returns all odd holes contained in {\tt G}. - Description - Text - The method is based on work of Francisco-Ha-Van Tuyl, looking at the associated primes - of the square of the Alexander dual of the edge ideal. An odd hole is an odd induced - cycle of length at least 5. - Example - R = QQ[x_1..x_6]; - G = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6}) --5-cycle and a triangle - allOddHoles G --only the 5-cycle should appear - H = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6,x_1*x_4}) --no odd holes - allOddHoles H - SeeAlso - allEvenHoles - hasOddHole -/// - - ------------------------------------------------------------- --- DOCUMENTATION antiCycle ------------------------------------------------------------- - -doc /// - Key - antiCycle - (antiCycle, Ring) - (antiCycle, Ring, ZZ) - (antiCycle, List) - Headline - returns a graph of an anticycle. - Usage - C = antiCycle R or C = antiCycle(R,N) or C = antiCycle L - Inputs - R:Ring - N:ZZ - length of anticycle - L:List - of vertices to make into the complement of a cycle in the order provided - Outputs - C:Graph - which is a anticycle on the vertices in {\tt L} or on the variables of {\tt R}. - Description - Text - This function is the reverse of the function @TO cycle @ by returning - the graph which is the complement of a cycle. - Example - R = QQ[a,b,c,d,e]; - antiCycle R - antiCycle(R,4) - antiCycle {e,c,d,b} - complementGraph antiCycle R == cycle R - SeeAlso - cycle - "Constructor Overview" -/// - - - ------------------------------------------------------------- --- DOCUMENTATION changeRing ------------------------------------------------------------- - -doc /// - Key - changeRing - (changeRing, HyperGraph, PolynomialRing, List) - Headline - replaces vertices with variables of a different ring - Usage - G = changeRing(H,R,L) or G = changeRing(H,R,L, MaximalEdges => B) - Inputs - H:HyperGraph - R:PolynomialRing - containing the new vertices as variables - L:List - of substitutions, one variable in R for each vertex of H - B:Boolean - Outputs - G:HyperGraph - over the ring R with edges obtained by making substitutions into the edges of H - Description - Text - This method is meant for moving a HyperGraph that is defined over - one ring, to another ring R. The parameter L must be a list containing - variables of R that should replace the vertices of H. For the most - basic way to use this method, see the first example: - Example - P = QQ[a,b,c]; - H = hyperGraph({a*b,b*c}); - S = QQ[x,y,z,w]; - changeRing(H,S,{x,z,y}) - Text - In the example above, {\tt a} is replaced with {\tt x}, {\tt b} is replaced with {\tt z}, and {\tt c} is replaced with {\tt y}. A more complex situation arises when two vertices of {\tt H} are replaced by the same variable. - Example - P = QQ[a,b,c]; - H = hyperGraph({a*b*c}); - G = hyperGraph({a*b,b*c}); - S = QQ[x,y,z,w]; - changeRing(H,S,{x,y,x}) - changeRing(G,S,{x,y,x}) - Text - Note that duplicate variables are removed from edges after substitution. - Duplicate edges are also reduced to a single edge. - As all HyperGraphs in this package have the property that no edge is a - subset of any other edge, some edges may need to be dropped - after substitution. This happens in the next example. - Example - P = QQ[a,b,c]; - H = hyperGraph({a*b,b*c}); - S = QQ[x,y]; - changeRing(H,S,{x,y,y}) - changeRing(H,S,{x,y,y},MaximalEdges=>true) - Text - By default, changeRing uses minimal edges that appear after substitution to - construct its output. The optional argument @TO MaximalEdges@ allows - one to get the maximal edges instead. - SeeAlso - inducedHyperGraph -/// - - - ------------------------------------------------------------- --- DOCUMENTATION chromaticNumber ------------------------------------------------------------- - -doc /// - Key - chromaticNumber - (chromaticNumber, HyperGraph) - Headline - computes the chromatic number of a hypergraph - Usage - c = chromaticNumber H - Inputs - H:HyperGraph - Outputs - i:ZZ - the chromatic number of {\tt H} - Description - Text - Returns the chromatic number, the smallest number of colors needed to color vertices of a graph. This method - is based upon a result of Francisco-Ha-Van Tuyl which relates the chromatic number to an ideal membership problem. - Example - S = QQ[a..f]; - c4 = cycle(S,4) -- 4-cycle; chromatic number = 2 - c5 = cycle(S,5) -- 5-cycle; chromatic number = 3 - k6 = completeGraph S -- complete graph on 6 vertices; chromatic number = 6 - chromaticNumber c4 - chromaticNumber c5 - chromaticNumber k6 -/// - - - ------------------------------------------------------------- --- DOCUMENTATION cliqueComplex ------------------------------------------------------------- - -doc /// - Key - cliqueComplex - (cliqueComplex, Graph) - Headline - returns the clique complex of a graph - Usage - D = cliqueComplex G - Inputs - G:Graph - Outputs - D:SimplicialComplex - the clique complex of {\tt G} - Description - Text - This function returns the clique complex of a graph $G$. This is the simplicial - complex whose faces correspond to the cliques in the graph. That is, - $F = \{x_{i_1},...,x_{i_s}\}$ is a face of the clique complex of $G$ if and only - if the induced graph on $\{x_{i_1},...,x_{i_s}\}$ is a clique of $G$. - Example - R = QQ[w,x,y,z]; - e = graph {w*x,w*y,x*y,y*z} -- clique on {w,x,y} and {y,z} - cliqueComplex e -- max facets {w,x,y} and {y,z} - g = completeGraph R - cliqueComplex g - SeeAlso - cliqueNumber - getCliques - getMaxCliques -/// - - - ------------------------------------------------------------- --- DOCUMENTATION cliqueNumber ------------------------------------------------------------- - -doc /// - Key - cliqueNumber - (cliqueNumber, Graph) - Headline - computes the clique number of a graph - Usage - c = cliqueNumber G - Inputs - G:Graph - Outputs - i:ZZ - the clique number of {\tt G} - Description - Text - cliqueNumber returns the clique number of a graph, the size of the largest clique - contained in the graph. This number is also related to the dimension of - the clique complex of the graph. - Example - R = QQ[a..d]; - cliqueNumber completeGraph R - G = graph({a*b,b*c,a*c,a*d}) - cliqueNumber G - dim cliqueComplex G + 1 == cliqueNumber G - SeeAlso - cliqueComplex - getCliques - getMaxCliques - -/// - - - ------------------------------------------------------------- --- DOCUMENTATION complementGraph ------------------------------------------------------------- - -doc /// - Key - complementGraph - (complementGraph, Graph) - (complementGraph, HyperGraph) - Headline - returns the complement of a graph or hypergraph - Usage - g = complementGraph G \n h = complementGraph H - Inputs - G:Graph - H:HyperGraph - Outputs - g:Graph - the complement of G, whose edges are the set of edges not in G - h:HyperGraph - the complement of H, whose edge set is found by taking the complement of each - edge of H in the vertex set - Description - Text - The function complementGraph finds the complement of a graph and hypergraph. Note - that function behaves differently depending upon the type. When applied to a graph, - complementGraph returns the graph whose edge set is the set of edges not in G. - When applied to a hypergraph, the edge set is found by taking the complement of - each edge of H in the vertex set. - Example - R = QQ[a,b,c,d,e]; - c5 = graph {a*b,b*c,c*d,d*e,e*a}; -- graph of the 5-cycle - complementGraph c5 -- the graph complement of the 5-cycle - c5hypergraph = hyperGraph c5 -- the 5-cycle, but viewed as a hypergraph - complementGraph c5hypergraph - Caveat - Notice that {\tt complementGraph} works differently on graphs versus hypergraphs. -/// - ------------------------------------------------------------- --- DOCUMENTATION completeGraph ------------------------------------------------------------- - -doc /// - Key - completeGraph - (completeGraph, Ring) - (completeGraph, Ring, ZZ) - (completeGraph, List) - Headline - returns a complete graph. - Usage - K = completeGraph R \n K = completeGraph(R,n) \n K = completeGraph L - Inputs - R:Ring - n:ZZ - number of variables to use - L:List - of vertices to make into a complete graph - Outputs - K:Graph - which is a complete graph on the vertices in {\tt L} or on the variables of {\tt R} - Description - Text - This function returns a special graph, the complete graph. The input specifies a set of vertices that - will have the property that every vertex is adjacent to every other vertex. Non-specified vertices are - treated as isolated vertices. - Example - R = QQ[a,b,c,d,e]; - completeGraph R - completeGraph(R,3) - completeGraph {a,c,e} - SeeAlso - completeMultiPartite - "Constructor Overview" -/// - ------------------------------------------------------------- --- DOCUMENTATION completeMulitPartite ------------------------------------------------------------- - -doc /// - Key - completeMultiPartite - (completeMultiPartite, Ring, ZZ,ZZ) - (completeMultiPartite, Ring, List) - Headline - returns a complete multipartite graph. - Usage - K = completeMultiPartite(R,n,m) \n K = completeMultiPartite(R,L) - Inputs - R:Ring - n:ZZ - number of partitions - m:ZZ - size of each partition - L:List - of integers giving the size of each partition, or a list of partitions which are lists of variables - Outputs - K:Graph - which is the complete multipartite graph on the given partitions - Description - Text - A complete multipartite graph is a graph with a partition of the vertices - such that every pair of vertices, not both from the same partition, - is an edge of the graph. The partitions can be specified by their number - and size, by a list of sizes, or by an explicit partition of the variables. - Not all variables of the ring need to be used. - Example - R = QQ[a,b,c,x,y,z]; - completeMultiPartite(R,2,3) - completeMultiPartite(R,{2,4}) - completeMultiPartite(R,{{a,b,c,x},{y,z}}) - Text - When {\tt n} is the number of variables and {\tt M = 1}, we recover the complete graph. - Example - R = QQ[a,b,c,d,e]; - t1 = completeMultiPartite(R,5,1) - t2 = completeGraph R - t1 == t2 - SeeAlso - completeGraph - "Constructor Overview" -/// - ------------------------------------------------------------- --- DOCUMENTATION connectedComponents ------------------------------------------------------------- - -doc /// - Key - connectedComponents - (connectedComponents, HyperGraph) - Headline - returns the connected components of a hypergraph - Usage - L = connectedComponents H - Inputs - H:HyperGraph - Outputs - L:List - of lists of vertices. Each list of vertices is a connected component of H. - Description - Text - The connected components of a hypergraph are sets of vertices in which - each vertex is connected to each other by a path. Each connected component - is disjoint and vertices that are not contained in any edge do not appear in - any connected component. - Example - R = QQ[a..l]; - H = hyperGraph {a*b*c, c*d, d*e*f, h*i, i*j, l} - L = connectedComponents H - apply(L, C -> inducedHyperGraph(H,C)) - SeeAlso - isConnected - numConnectedComponents -/// - - - ------------------------------------------------------------- --- DOCUMENTATION coverIdeal ------------------------------------------------------------- - -doc /// - Key - coverIdeal - (coverIdeal, HyperGraph) - Headline - creates the cover ideal of a (hyper)graph - Usage - I = coverIdeal H - Inputs - H:HyperGraph - Outputs - I:MonomialIdeal - the cover ideal of H - Description - Text - Returns the monomial ideal generated by the minimal vertex covers. This is also the Alexander dual - of the edge ideal of the hypergraph {\tt H}. - Example - S = QQ[a,b,c,d,e,f]; - k6 = completeGraph S -- complete graph on 6 vertices - coverIdeal k6 -- each generator corresponds to a minimal vertex of k6 - h = hyperGraph {a*b*c,c*d,d*e*f} - coverIdeal h - dual coverIdeal h == edgeIdeal h - SeeAlso - dual - edgeIdeal - vertexCoverNumber - vertexCovers -/// - ------------------------------------------------------------- --- DOCUMENTATION cycle ------------------------------------------------------------- - -doc /// - Key - cycle - (cycle, Ring) - (cycle, Ring, ZZ) - (cycle, List) - Headline - returns a graph cycle - Usage - C = cycle R \n C = cycle(R,n) \n C = cycle L - Inputs - R:Ring - n:ZZ - length of cycle - L:List - of vertices to make into a cycle in the order provided - Outputs - C:Graph - which is a cycle on the vertices in {\tt L} or on the variables of {\tt R}. - Description - Text - Give a list of vertices (perhaps in some specified order), this function returns the graph of the - cycle on those vertices, using the order given or the internal ordering of the - @TO vertices @. Unspecified vertices are treated as isolated vertices. - Example - R = QQ[a,b,c,d,e]; - cycle R - cycle(R,3) - cycle {e,c,d,b} - R = QQ[a,c,d,b,e];-- variables given different order - cycle R - SeeAlso - antiCycle - "Constructor Overview" -/// - - ------------------------------------------------------------- --- DOCUMENTATION degreeVertex ------------------------------------------------------------- -doc /// - Key - degreeVertex - (degreeVertex, HyperGraph, ZZ) - (degreeVertex, HyperGraph, RingElement) - Headline - returns the degree of a vertex. - Usage - d = degreeVertex(H,n) \n d = degreeVertex(H,V) - Inputs - H:HyperGraph - n:ZZ - the index of a vertex - V:RingElement - a vertex/variable of the HyperGraph - Outputs - d:ZZ - which is the degree of vertex {\tt V} (or vertex number {\tt n}) - Description - Text - The degree of a vertex in a (hyper)graph is the number of edges that contain the vertex. - In a graph, the degree is also the number of elements in the neighbor set of a vertex. - Example - S = QQ[a,b,c,d,e]; - k5 = completeGraph S - dv = degreeVertex(k5,a) - n = neighbors(k5,a) - #n == dv - degreeVertex(k5,2) - h = hyperGraph {a*b*c,c*d,a*d*e,b*e,c*e} - degreeVertex(h,a) - degreeVertex(h,2) -- degree of c - SeeAlso - neighbors - vertices -/// - - - ------------------------------------------------------------- --- DOCUMENTATION deleteEdges ------------------------------------------------------------- - -doc /// - Key - deleteEdges - (deleteEdges, HyperGraph, List) - Headline - returns the (hyper)graph with specified edges removed - Usage - h = deleteEdges(H, S) - Inputs - H:HyperGraph - S:List - which is a subset of the edges of the graph or hypergraph - Outputs - h:HyperGraph - the hypergraph with edges in S removed - Description - Text - This function enables the user to remove specified edges from a graph to form - a subgraph. - Example - S = QQ[a,b,c,d,e]; - g = cycle S - T = {{a,b},{d,e}} - gprime = deleteEdges (g,T) - h = hyperGraph {a*b*c,c*d*e,a*e} - T = edges h - hprime = deleteEdges (h,T) -/// - - - ------------------------------------------------------------- --- DOCUMENTATION edgeIdeal ------------------------------------------------------------- - - -doc /// - Key - edgeIdeal - (edgeIdeal, HyperGraph) - Headline - creates the edge ideal of a (hyper)graph - Usage - I = edgeIdeal H - Inputs - H:HyperGraph - Outputs - I:MonomialIdeal - the edge ideal of H - Description - Text - The edge ideal of a (hyper)graph is a square-free monomial ideal where the - generators correspond to the edges of a (hyper)graph. Along with @TO coverIdeal @, - the function edgeIdeal enables us to translate many graph theoretic properties into - algebraic properties. - - When the input is a finite simple graph, that is, a graph with no loops or multiple - edges, then the edge ideal is a quadratic square-free monomial ideal generated by - terms of the form $x_ix_j$ whenever $\{x_i,x_j\}$ is an edge of the graph. - Example - S = QQ[a..e]; - c5 = cycle S - edgeIdeal c5 - graph flatten entries gens edgeIdeal c5 == c5 - k5 = completeGraph S - edgeIdeal k5 - Text - When the input is a hypergraph, the edge ideal is a square-free monomial ideal - generated by monomials of the form $x_{i_1}x_{i_2}...x_{i_s}$ whenever - $\{x_{i_1},...,x_{i_s}\}$ is an edge of the hypergraph. Because all of our - hypergraphs are clutters, that is, no edge is allowed to be a subset of another edge, - we have a bijection between the generators of the edge ideal of hypergraph and the edges - of the hypergraph. - Example - S = QQ[z_1..z_8]; - h = hyperGraph {{z_1,z_2,z_3},{z_2,z_3,z_4,z_5},{z_4,z_5,z_6},{z_6,z_7,z_8}} - edgeIdeal h - SeeAlso - coverIdeal -/// - - - ------------------------------------------------------------- --- DOCUMENTATION edges ------------------------------------------------------------- - - -doc /// - Key - edges - (edges, HyperGraph) - Headline - gets the edges of a (hyper)graph. - Usage - E = edges(H) - Inputs - H:HyperGraph - Outputs - E:List - of the edges of {\tt H}. - Description - Text - This function takes a (hyper)graph, and returns the edges set of the (hyper)graph. - Example - S = QQ[a..d]; - g = graph {a*b,b*c,c*d,d*a} -- the four cycle - edges g - h = hyperGraph{a*b*c} - edges h - k4 = completeGraph S - edges k4 - SeeAlso - vertices -/// - - ------------------------------------------------------------- --- DOCUMENTATION getCliques ------------------------------------------------------------- - -doc /// - Key - getCliques - (getCliques, Graph, ZZ) - (getCliques, Graph) - Headline - returns cliques in a graph - Usage - C = getCliques(G,d) or C = getCliques G - Inputs - G:Graph - d:ZZ - representing the size of the cliques desired - Outputs - C:List - of cliques of size {\tt d} or, if no {\tt d} is entered, all cliques. - SeeAlso - cliqueNumber - Description - Text - A clique of a graph is a subset of its vertices which induces a complete subgraph. - That is, a set of vertices is a clique if every pair of vertices in the set form an edge of the graph. - This function returns all cliques of a specified size, and if no size is given, it returns all cliques. Note that - all the edges of the graph are considered cliques of size two. - Example - R = QQ[a..d]; - G = completeGraph R - getCliques(G,3) - getCliques(G,4) - getCliques G - -/// - - ------------------------------------------------------------- --- DOCUMENTATION getEdge ------------------------------------------------------------- - -doc /// - Key - getEdge - (getEdge, HyperGraph, ZZ) - Headline - gets the n-th edge in a (hyper)graph - Usage - E = getEdge(H,n) - Inputs - H:HyperGraph - n:ZZ - an index of an edge in {\tt H} - Outputs - E:List - which is the {\tt n}-th edge of {\tt H} - Description - Text - This function returns the n^{th} edge of the (hyper)graph. - Example - S = QQ[a..f]; - g = cycle S - edges g - getEdge (g,3) -- counting starts from 0, so the 4th element in the above list - h = hyperGraph {a*b*c*d,d*e,a*f*c,a*d*f} - getEdge (h,0) -- first edge - SeeAlso - edges - getEdgeIndex -/// - ------------------------------------------------------------- --- DOCUMENTATION getEdgeIndex ------------------------------------------------------------- - -doc /// - Key - getEdgeIndex - (getEdgeIndex, HyperGraph, List) - (getEdgeIndex, HyperGraph, RingElement) - Headline - finds the index of an edge in a HyperGraph - Usage - n = getEdgeIndex(H,E) or n = getEdgeIndex(H,M) - Inputs - H:HyperGraph - E:List - of vertices - M:RingElement - a monomial of vertices - Outputs - n:ZZ - which is the index of {\tt E} as an edge of {\tt H}. If {\tt E} is not in {\tt H} - then -1 is returned - Description - Text - This function returns the index of the edge of the (hyper)graph, where the ordering - is determined by the internal ordering of the edges. Note that the internal order of the - edges may not be preserved by methods which change the hypergraph - (i.e. @TO inducedHyperGraph@, @TO changeRing@, @TO (hyperGraph, MonomialIdeal)@, etc.). - Example - S = QQ[z_1..z_8]; - h = hyperGraph {z_2*z_3*z_4,z_6*z_8,z_7*z_5,z_1*z_6*z_7,z_2*z_4*z_8} - edges h - getEdgeIndex (h,{z_2,z_4,z_8}) -- although entered last, edge is internally stored in 4th spot (counting begins at 0) - getEdge(h,3) - getEdgeIndex (h,{z_1,z_2}) -- not in the edge list - SeeAlso - getEdge - isEdge -/// - ------------------------------------------------------------- --- DOCUMENTATION getGoodLeaf ------------------------------------------------------------- - -doc /// - Key - getGoodLeaf - (getGoodLeaf, HyperGraph) - Headline - returns an edge that is a good leaf - Usage - L = getGoodLeaf(H) - Inputs - H:HyperGraph - Outputs - L:List - of vertices that are an edge in H that form a good leaf. - Description - Text - A good leaf of a hypergraph {\tt H} is an edge {\tt L} whose intersections - with all other edges form a totally ordered set. It follows that - {\tt L} must have a free vertex. In the graph setting, a good leaf is - an edge containing a vertex of degree one. The notion of a good - leaf was introduced by X. Zheng in her PhD thesis (2004). - Example - R = QQ[a..g]; - H = hyperGraph {a*b*c*d, b*c*d*e, c*d*f, d*g, e*f*g}; - getGoodLeaf(H) - SeeAlso - getGoodLeafIndex - hasGoodLeaf - isGoodLeaf -/// - ------------------------------------------------------------- --- DOCUMENTATION getGoodLeafIndex ------------------------------------------------------------- - -doc /// - Key - getGoodLeafIndex - (getGoodLeafIndex, HyperGraph) - Headline - returns the index of an edge that is a good leaf - Usage - n = getGoodLeafIndex(H) - Inputs - H:HyperGraph - Outputs - n:ZZ - the index of an edge in H of a good leaf. - Returns -1 if H does not have a good leaf. - Description - Text - A good leaf of hypergraph {\tt H} is an edge {\tt L} whose intersections - with all other edges form a totally ordered set. It follows that - {\tt L} must have a free vertex. In the graph setting, a good leaf is - an edge containing a vertex of degree one. - The notion of a good leaf was introduced by X. Zheng in her PhD thesis (2004). - Example - R = QQ[a..g]; - H = hyperGraph {b*c*d*e, a*b*c*d, c*d*f, d*g, e*f*g}; - getGoodLeaf(H) - edges(H) - getGoodLeafIndex(H) - SeeAlso - getGoodLeaf - hasGoodLeaf - isGoodLeaf -/// - ------------------------------------------------------------- --- DOCUMENTATION getMaxCliques ------------------------------------------------------------- - -doc /// - Key - getMaxCliques - (getMaxCliques, Graph) - Headline - returns maximal cliques in a graph - Usage - C = getMaxCliques G - Inputs - G:Graph - Outputs - C:List - of cliques of maximal size contained in {\tt G} - Description - Text - The function returns all cliques of maximal size in a graph as a list of lists. For more details, see @TO getCliques@. - Example - R = QQ[a..d]; - G = completeGraph R - getMaxCliques G - H = graph({a*b,b*c,a*c,c*d,b*d}) - getMaxCliques H - SeeAlso - cliqueNumber - getCliques -/// - ------------------------------------------------------------- --- DOCUMENTATION hasGoodLeaf ------------------------------------------------------------- - -doc /// - Key - hasGoodLeaf - (hasGoodLeaf, HyperGraph) - Headline - determines if a HyperGraph contains a good leaf - Usage - b = hasGoodLeaf(H) - Inputs - H:HyperGraph - Outputs - b:Boolean - true if H contains an edge that is a good leaf. - Description - Text - A good leaf of hypergraph {\tt H} is an edge {\tt L} whose intersections - with all other edges form a totally ordered set. It follows that - {\tt L} must have a free vertex. In the graph setting, a good leaf is - an edge containing a vertex of degree one. The notion of a good - leaf was introduced by X. Zheng in her PhD thesis (2004). - Example - R = QQ[a..g]; - H = hyperGraph {b*c*d*e, a*b*c*d, c*d*f, d*g, e*f*g}; - hasGoodLeaf(H) - getGoodLeaf(H) - SeeAlso - getGoodLeaf - getGoodLeafIndex - isGoodLeaf -/// - ------------------------------------------------------------- --- DOCUMENTATION hasOddHole ------------------------------------------------------------- - -doc /// - Key - hasOddHole - (hasOddHole, Graph) - Headline - tells whether a graph contains an odd hole. - Usage - b = hasOddHole G - Inputs - G:Graph - Outputs - b:Boolean - returns {\tt true} if {\tt G} has an odd hole and {\tt false} otherwise - Description - Text - An odd hole is an odd induced cycle of length at least 5. - The method is based on work of Francisco-Ha-Van Tuyl, looking at the associated primes - of the square of the Alexander dual of the edge ideal. - Example - R = QQ[x_1..x_6]; - G = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6}) --5-cycle and a triangle - hasOddHole G - H = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6,x_1*x_4}) --no odd holes - hasOddHole H - SeeAlso - allOddHoles -/// - - - ------------------------------------------------------------- --- DOCUMENTATION hyperGraphToSimplicialComplex ------------------------------------------------------------- - -doc /// - Key - hyperGraphToSimplicialComplex - (hyperGraphToSimplicialComplex, HyperGraph) - Headline - turns a (hyper)graph into a simplicial complex - Usage - D = hyperGraphToSimplicialComplex H - Inputs - H:HyperGraph - Outputs - D:SimplicialComplex - whose facets are given by the edges of H - Description - Text - This function changes the type of a (hyper)graph to a simplicial complex where - the facets of the simplicial complex are given by the edge set of the (hyper)graph. - This function is the reverse of @TO simplicialComplexToHyperGraph @. This function enables the users - to make use of the functions in the package @TO SimplicialComplexes @ - Example - R = QQ[x_1..x_6]; - G = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6}) --5-cycle and a triangle - DeltaG = hyperGraphToSimplicialComplex G - hyperGraphDeltaG = simplicialComplexToHyperGraph DeltaG - GPrime = graph(hyperGraphDeltaG) - G === GPrime - SeeAlso - simplicialComplexToHyperGraph - "Constructor Overview" -/// - - ------------------------------------------------------------- --- DOCUMENTATION incidenceMatrix ------------------------------------------------------------- - -doc /// - Key - incidenceMatrix - (incidenceMatrix, HyperGraph) - Headline - returns the incidence matrix of a hypergraph - Usage - M = incidenceMatrix H - Inputs - H:HyperGraph - Outputs - M:Matrix - the incidence matrix of the hypergraph - Description - Text - This function returns the incidence matrix of the inputted hypergraph. - The rows of the matrix are indexed by the variables of the hypergraph - and the columns are indexed by the edges. The (i,j)^{th} entry in the - matrix is 1 if vertex i is contained in edge j, and is 0 otherwise. - The order of the rows and columns are determined by the internal order of - the vertices and edges. See @TO edges@ and @TO vertices@. - Example - S = QQ[a..f]; - g = hyperGraph {a*b*c*d,c*e,e*f} - incidenceMatrix g - T = QQ[f,e,d,c,b,a]; - h = hyperGraph {a*b*c*d,c*e,e*f} - incidenceMatrix h -- although the same graph, matrix is different since variables have different ordering - SeeAlso - adjacencyMatrix - edges - vertices -/// - ------------------------------------------------------------- --- DOCUMENTATION independenceComplex ------------------------------------------------------------- - - -doc /// - Key - independenceComplex - (independenceComplex, HyperGraph) - Headline - returns the independence complex of a (hyper)graph - Usage - D = independenceComplex H - Inputs - H:HyperGraph - Outputs - D:SimplicialComplex - the independence complex associated to the (hyper)graph - Description - Text - This function associates to a (hyper)graph a simplicial complex whose faces correspond - to the independent sets of the (hyper)graph. See, for example, the paper - of A. Van Tuyl and R. Villarreal - "Shellable graphs and sequentially Cohen-Macaulay bipartite graphs," - Journal of Combinatorial Theory, Series A 115 (2008) 799-814. - Example - S = QQ[a..e]; - g = graph {a*b,b*c,c*d,d*e,e*a} -- the 5-cycle - independenceComplex g - h = hyperGraph {a*b*c,b*c*d,d*e} - independenceComplex h - Text - Equivalently, the independence complex is the simplicial complex associated - to the edge ideal of the (hyper)graph H via the Stanley-Reisner correspondence. - Example - S = QQ[a..e]; - g = graph {a*b,b*c,a*c,d*e,a*e} - Delta1 = independenceComplex g - Delta2 = simplicialComplex edgeIdeal g - Delta1 === Delta2 - SeeAlso - independenceNumber -/// - - - - ------------------------------------------------------------- --- DOCUMENTATION independenceNumber ------------------------------------------------------------- - - -doc /// - Key - independenceNumber - (independenceNumber, Graph) - Headline - determines the independence number of a graph - Usage - d = independenceNumber G - Inputs - G:Graph - Outputs - d:ZZ - the independence number (the number of independent vertices) in {\tt G} - Description - Text - This function returns the maximum number of independent vertices in a graph. This number - can be found by computing the dimension of the simplicial complex whose faces are the independent - sets (see @TO independenceComplex @) and adding 1 to this number. - Example - R = QQ[a..e]; - c4 = graph {a*b,b*c,c*d,d*a} -- 4-cycle plus an isolated vertex!!!! - c5 = graph {a*b,b*c,c*d,d*e,e*a} -- 5-cycle - independenceNumber c4 - independenceNumber c5 - dim independenceComplex c4 + 1 == independenceNumber c4 - - SeeAlso - independenceComplex -/// - ------------------------------------------------------------- --- DOCUMENTATION inducedHyperGraph ------------------------------------------------------------- - - -doc /// - Key - inducedHyperGraph - (inducedHyperGraph, HyperGraph, List) - Headline - returns the induced subgraph of a (hyper)graph. - Usage - h = inducedHyperGraph H - Inputs - H:HyperGraph - L:List - of vertices (i.e. variables in the ring of {\tt H}) - Outputs - h:HyperGraph - the induced subgraph of {\tt H} whose edges are contained in {\tt L} - Description - Text - This function returns the induced subgraph of a (hyper)graph on a specified set of vertices. The function - enables the user to create subgraphs of the original (hyper)graph. - - The default option is for the ring of the induced subgraph to contain only - variables in {\tt L}. Then the current ring must be changed before working with the induced subgraph. - We use this setup to avoid having a lot of isolated vertices in the induced (hyper)graph. However, one - can set the option @TO OriginalRing@ to {\tt true} if one wants to give the induced (hyper)graph the - same ring as the original (hyper)graph. - - Note: Since @TO Graph@ is a @TO Type@ of @TO HyperGraph@, {\tt inducedHyperGraph} can be used for graphs. There - is no separate method installed. - Example - R = QQ[a,b,c,d,e]; - G = graph {a*b,b*c,c*d,d*e,e*a} -- graph of the 5-cycle - H1 = inducedHyperGraph(G,{b,c,d,e}) - H2 = inducedHyperGraph(G,{a,b,d,e}) - use ring H1 - inducedHyperGraph(H1,{c,d,e}) - use ring G - inducedHyperGraph(G,{b,c,d,e},OriginalRing=>true) --H1 but in bigger ring - Text - Equivalently, one can use @TO changeRing@ to move the induced hypergraph - back into the original ring. - Example - R = QQ[a,b,c,d,e]; - G = graph {a*b,b*c,c*d,d*e,e*a} -- graph of the 5-cycle - H = inducedHyperGraph(G,{b,c,d}) - changeRing(H,R,{b,c,d}) - SeeAlso - deleteEdges - changeRing -/// - - - ------------------------------------------------------------- --- DOCUMENTATION isBipartite ------------------------------------------------------------- - -doc /// - Key - isBipartite - (isBipartite, Graph) - Headline - determines if a graph is bipartite - Usage - b = isBipartite G - Inputs - G:Graph - Outputs - b:Boolean - returns {\tt true} if {\tt G} is bipartite, {\tt false} otherwise - Description - Text - The function {\tt isBipartite} determines if a given graph is bipartite. A graph is - said to be bipartite if the vertices can be partitioned into two sets W and Y such - that every edge has one vertex in W and the other in Y. Since a graph is bipartite - if and only if its chromatic number is 2, we can check if a graph is bipartite by - computing its chromatic number. - Example - S = QQ[a..e]; - t = graph {a*b,b*c,c*d,a*e} -- a tree (and thus, bipartite) - c5 = cycle S -- 5-cycle (not bipartite) - isBipartite t - isBipartite c5 - SeeAlso - chromaticNumber -/// - - - ------------------------------------------------------------- --- DOCUMENTATION isChordal ------------------------------------------------------------- - -doc /// - Key - isChordal - (isChordal, Graph) - Headline - determines if a graph is chordal - Usage - b = isChordal G - Inputs - G:Graph - Outputs - b:Boolean - true if the graph is chordal - Description - Text - A graph is chordal if the graph has no induced cycles of length 4 or more (triangles are allowed). - To check if a graph is chordal, we make use of a characterization of Fr\"oberg - (see "On Stanley-Reisner rings," Topics in algebra, Part 2 (Warsaw, 1988), 57-70, - Banach Center Publ., 26, Part 2, PWN, Warsaw, 1990.) which says that a graph G is - chordal if and only if the edge ideal of G^c has a linear resolution. - Example - S = QQ[a..e]; - C = cycle S; - isChordal C - D = graph {a*b,b*c,c*d,a*c}; - isChordal D - E = completeGraph S; - isChordal E - /// - - ------------------------------------------------------------- --- DOCUMENTATION isCM ------------------------------------------------------------- - -doc /// - Key - isCM - (isCM, HyperGraph) - Headline - determines if a (hyper)graph is Cohen-Macaulay - Usage - b = isCM H - Inputs - H:HyperGraph - Outputs - b:Boolean - true if the @TO edgeIdeal@ of {\tt H} is Cohen-Macaulay - Description - Text - This uses the edge ideal notion of Cohen-Macaulayness; a hypergraph is called C-M if - and only if its edge ideal is C-M. - Example - R = QQ[a..e]; - C = cycle R; - UnmixedTree = graph {a*b, b*c, c*d}; - MixedTree = graph {a*b, a*c, a*d}; - isCM C - isCM UnmixedTree - isCM MixedTree - SeeAlso - isSCM - edgeIdeal -/// - ------------------------------------------------------------- --- DOCUMENTATION isConnected ------------------------------------------------------------- - -doc /// - Key - isConnected - (isConnected, HyperGraph) - Headline - determines if a (hyper)graph is connected - Usage - b = isConnected H - Inputs - H:Graph - Outputs - b:Boolean - returns {\tt true} if {\tt H} is connected, {\tt false} otherwise - Description - Text - This function checks if the (hyper)graph is connected. It relies on the @TO numConnectedComponents @. - Example - S = QQ[a..e]; - g = graph {a*b,b*c,c*d,d*e,a*e} -- the 5-cycle (connected) - h = graph {a*b,b*c,c*a,d*e} -- a 3-cycle and a disjoint edge (not connected) - isConnected g - isConnected h - SeeAlso - connectedComponents - numConnectedComponents -/// - - - - - - ------------------------------------------------------------- --- DOCUMENTATION isEdge ------------------------------------------------------------- - -doc /// - Key - isEdge - (isEdge, HyperGraph, List) - (isEdge, HyperGraph, RingElement) - Headline - determines if an edge is in a (hyper)graph - Usage - b = isEdge(H,E) \n b = isEdge(H,M) - Inputs - H:HyperGraph - E:List - of vertices. - M:RingElement - a monomial representing an edge. - Outputs - b:Boolean - which is true iff {\tt E} (or {\tt support M}) is an edge of {\tt H} - Description - Text - This function checks if a given edge, represented either as a list or monomial, belongs - to a given (hyper)graph. - Example - S = QQ[z_1..z_8]; - h = hyperGraph {z_2*z_3*z_4,z_6*z_8,z_7*z_5,z_1*z_6*z_7,z_2*z_4*z_8}; - edges h - isEdge (h,{z_2,z_4,z_8}) - isEdge (h,z_2*z_3*z_4) - isEdge (h,{z_1,z_2}) - SeeAlso - getEdgeIndex -/// - ------------------------------------------------------------- --- DOCUMENTATION isForest ------------------------------------------------------------- - -doc /// - Key - isForest - (isForest, Graph) - (isForest, HyperGraph) - Headline - determines whether a (hyper)graph is a forest - Usage - b = isForest G or b = isForest H - Inputs - G:Graph - H:HyperGraph - Outputs - b:Boolean - true if G (or H) is a forest - Description - Text - This function determines if a graph or hypergraph is a forest. A graph is a forest if - if the graph has no cycles. We say that a hypergraph is forest if each - connected component is a tree in the sense of S. Faridi. See the paper - "The facet ideal of a simplicial complex," Manuscripta Mathematica 109, 159-174 (2002). - Example - S = QQ[a..f]; - t = graph {a*b,a*c,a*e} - isForest t - h = hyperGraph {a*b*c,c*d*e,b*d*f} - isForest h -/// - ------------------------------------------------------------- --- DOCUMENTATION isGoodLeaf ------------------------------------------------------------- - -doc /// - Key - isGoodLeaf - (isGoodLeaf, HyperGraph, ZZ) - Headline - determines if an edge is a good leaf - Usage - b = getGoodLeaf(H,n) - Inputs - H:HyperGraph - n:ZZ - index of an edge - Outputs - b:Boolean - true if edge {\tt n} of {\tt H} is a good leaf. - Description - Text - A good leaf of hypergraph {\tt H} is an edge {\tt L} whose intersections - with all other edges form a totally ordered set. It follows that - {\tt L} must have a free vertex. In the graph setting, a good leaf is - an edge containing a vertex of degree one. The notion of a good - leaf was introduced by X. Zheng in her PhD thesis (2004). - Example - R = QQ[a..g]; - H = hyperGraph {a*b*c*d, b*c*d*e, c*d*f, d*g, e*f*g}; - edges(H) - isGoodLeaf(H,0) - isGoodLeaf(H,1) - SeeAlso - getGoodLeaf - getGoodLeafIndex - hasGoodLeaf -/// - ------------------------------------------------------------- --- DOCUMENTATION isGraph ------------------------------------------------------------- - -doc /// - Key - isGraph - (isGraph, HyperGraph) - Headline - determines if a hypergraph is a graph - Usage - b = isGraph H - Inputs - H:HyperGraph - Outputs - b:Boolean - {\tt true} if all edges in {\tt H} have size two - Description - Example - QQ[a,b,c,d]; - isGraph(hyperGraph {a*b,b*c,c*d}) - isGraph(hyperGraph {a*b,b*c*d}) - isGraph(hyperGraph {a*b,b*c,d}) -/// - ------------------------------------------------------------- --- DOCUMENTATION isLeaf ------------------------------------------------------------- - -doc /// - Key - isLeaf - (isLeaf, Graph, ZZ ) - (isLeaf, HyperGraph, ZZ) - (isLeaf, HyperGraph, RingElement ) - Headline - determines if an edge (or vertex) is a leaf of a (hyper)graph - Usage - b = isLeaf(G,N) or b = isLeaf(H,n) or b = isLeaf(H,V) - Inputs - G:Graph - H:HyperGraph - n:ZZ - an index of an edge - V:RingElement - a vertex - Outputs - b:Boolean - true if edge {\tt n} is a leaf or if vertex {\tt V} has degree 1 - Description - Text - An edge in a graph is a leaf if it contains a vertex of degree one. - An edge {\tt E} in a hypergraph is a leaf if there is another edge {\tt B} with the - property that for all edges {\tt F} (other than {\tt E}), the intersection of {\tt F} - with {\tt E} is contained in the intersection of {\tt B} with {\tt E}. - - A vertex of a graph is a leaf if it has degree one. - A vertex of a hypergraph is a leaf if it is contained in precisely one - edge which is itself is leaf. - Example - R = QQ[a..f]; - G = graph {a*b,b*c,c*a,b*d}; - isLeaf(G, d) - isLeaf(G, getEdgeIndex(G, {b,d})) - isLeaf(G, a) - isLeaf(G, getEdgeIndex(G, {a,b})) - H = hyperGraph {a*b*c,b*d,c*e,b*c*f}; - K = hyperGraph {a*b*c,b*d,c*e}; - isLeaf(H, a) - isLeaf(H, getEdgeIndex(H, {a,b,c})) - isLeaf(K, a) - isLeaf(K, getEdgeIndex(K, {a,b,c})) - SeeAlso - isForest - isGoodLeaf -/// - ------------------------------------------------------------- --- DOCUMENTATION isPerfect ------------------------------------------------------------- - -doc /// - Key - isPerfect - (isPerfect, Graph) - Headline - determines whether a graph is perfect - Usage - b = isPerfect G - Inputs - G:Graph - Outputs - b:Boolean - which is {\tt true} if {\tt G} is perfect and {\tt false} otherwise - Description - Text - The algorithm uses the Strong Perfect Graph Theorem, which says that {\tt G} is - perfect if and only if neither {\tt G} nor its complement contains an odd hole. - @TO hasOddHole@ is used to determine whether these conditions hold. - Example - R = QQ[x_1..x_7]; - G = complementGraph cycle R; --odd antihole with 7 vertices - isPerfect G - H = cycle(R,4) - isPerfect H - - SeeAlso - hasOddHole -/// - ------------------------------------------------------------- --- DOCUMENTATION isSCM ------------------------------------------------------------- - -doc /// - Key - isSCM - (isSCM, HyperGraph) - Headline - determines if a (hyper)graph is sequentially Cohen-Macaulay - Usage - b = isSCM H - Inputs - H:HyperGraph - Outputs - b:Boolean - true if the @TO edgeIdeal@ of {\tt H} is sequentially Cohen-Macaulay - Description - Text - This uses the edge ideal notion of sequential Cohen-Macaulayness; a - hypergraph is called SCM if and only if its edge ideal is SCM. The - algorithm is based on work of Herzog and Hibi, using the Alexander - dual. {\tt H} is SCM if and only if the Alexander dual of the edge ideal - of {\tt H} is componentwise linear. - - There is an optional argument called @TO Gins@ for {\tt isSCM}. The - default value is {\tt false}, meaning that {\tt isSCM} takes the - Alexander dual of the edge ideal of {\tt H} and checks in all relevant - degrees to see if the ideal in that degree has a linear resolution. In - characteristic zero with the reverse-lex order, one can test for - componentwise linearity using gins, which may be faster in some cases. This - approach is based on work of Aramova-Herzog-Hibi and Conca. We make no attempt - to check the characteristic of the field or the monomial order, so use caution - when using this method. - Example - R = QQ[a..f]; - G = cycle(R,4) - isSCM G - H = graph(monomialIdeal(a*b,b*c,c*d,a*d,a*e)); --4-cycle with whisker - isSCM H - isSCM(H,Gins=>true) --use Gins technique - SeeAlso - isCM - edgeIdeal -/// - ------------------------------------------------------------- --- DOCUMENTATION lineGraph ------------------------------------------------------------- - -doc /// - Key - lineGraph - (lineGraph, HyperGraph) - Headline - returns the line graph of a (hyper)graph - Usage - L = lineGraph H - Inputs - H:HyperGraph - Outputs - L:Graph - the line graph of H - Description - Text - The line graph {\tt L} of a hypergraph {\tt H} has a vertex for each edge in {\tt H}. - Two vertices in {\tt L} are adjacent if their edges in {\tt H} share a vertex. - The order of the vertices in {\tt L} are determined by the implicit order - on the edges of {\tt H}. See @TO edges@. - Example - R = QQ[a..e]; - G = graph {a*b,a*c,a*d,d*e} - lineGraph G - SeeAlso - edges -/// - ------------------------------------------------------------- --- DOCUMENTATION neighbors ------------------------------------------------------------- - -doc /// - Key - neighbors - (neighbors, HyperGraph, RingElement) - (neighbors, HyperGraph, ZZ) - (neighbors, HyperGraph, List) - Headline - returns the neighbors of a vertex or list of vertices - Usage - N = neighbors(H,V) or N = neighbors(H,n) or N = neighbors(H,L) - Inputs - H:HyperGraph - V:RingElement - a vertex - n:ZZ - the index of a vertex - L:List - a list of vertices or indices of vertices - Outputs - N:List - of neighbors to the given vertex or vertices. - Description - Text - The vertices adjacent to vertex {\tt V} are called the neighbors of {\tt V}. The neighbors - of a list of vertices {\tt L} are those vertices which are not in {\tt L} and are adjacent - to a vertex in {\tt L}. - Example - R = QQ[a..f]; - G = graph {a*b, a*c, a*d, d*e, d*f}; - neighbors(G,a) - neighbors(G,0) - neighbors(G,{a,d}) - neighbors(G,{0,3}) - SeeAlso - degreeVertex - vertices -/// - ------------------------------------------------------------- --- DOCUMENTATION numConnectedComponents ------------------------------------------------------------- - -doc /// - Key - numConnectedComponents - (numConnectedComponents, HyperGraph) - Headline - returns the number of connected components in a (hyper)graph - Usage - d = numConnectedComponents H - Inputs - H:HyperGraph - Outputs - d:ZZ - the number of connected components of H - Description - Text - The function returns the number of connected components of a (hyper)graph. To count the number of components, - the algorithm turns {\tt H} into a simplicial complex, and then computes the rank of the 0^{th} reduced - homology group. This number plus 1 gives us the number of connected components. - Example - S = QQ[a..e]; - g = graph {a*b,b*c,c*d,d*e,a*e} -- the 5-cycle (connected) - h = graph {a*b,b*c,c*a,d*e} -- a 3-cycle and a disjoint edge (not connected) - numConnectedComponents g - numConnectedComponents h - SeeAlso - connectedComponents - isConnected -/// - - ------------------------------------------------------------- --- DOCUMENTATION numTriangles ------------------------------------------------------------- - -doc /// - Key - numTriangles - (numTriangles, Graph) - Headline - returns the number of triangles in a graph - Usage - d = numTriangles G - Inputs - G:Graph - Outputs - d:ZZ - the number of triangles contained in {\tt G} - Description - Text - The method is based on work of Francisco-Ha-Van Tuyl, looking at the associated primes - of the square of the Alexander dual of the edge ideal. The function counts the number - of these associated primes of height 3. - Example - R = QQ[x_1..x_6]; - G = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6}) --5-cycle and a triangle - numTriangles G - H = completeGraph R; - numTriangles H == binomial(6,3) - SeeAlso - allOddHoles - getCliques -/// - ------------------------------------------------------------- --- DOCUMENTATION randomGraph ------------------------------------------------------------- - -doc /// - Key - randomGraph - (randomGraph,PolynomialRing, ZZ) - Headline - returns a random graph - Usage - G = randomGraph(R,d) - Inputs - R:PolynomialRing - which gives the vertex set of {\tt G} - d:ZZ - the number of edges in {\tt G} - Outputs - G:Graph - a graph with {\tt d} edges on vertex set determined by {\tt R} - Description - Example - R = QQ[x_1..x_9]; - randomGraph(R,4) - randomGraph(R,4) - SeeAlso - randomUniformHyperGraph - randomHyperGraph - "Constructor Overview" -/// - - ------------------------------------------------------------- --- DOCUMENTATION randomHyperGraph ------------------------------------------------------------- - -doc /// - Key - randomHyperGraph - (randomHyperGraph,PolynomialRing,List) - Headline - returns a random hypergraph - Usage - H = randomHyperGraph(R,D) - Inputs - R:PolynomialRing - which gives the vertex set of {\tt H} - D:List - of integers that are the cardinalities of the edges of {\tt H} - Outputs - H:HyperGraph - a hypergraph with edges {\tt E_i} each of size {\tt D_i}. Returns {\tt null} if none can be found. - Description - Text - This method is not guaranteed to return a HyperGraph, even if one exists with the given edge sizes. This method - searches for a hypergraph with the given edge sizes using a random recursive algorithm. Limits can be placed on the - both number of recursive steps taken (see @TO BranchLimit@) and on the time taken (see @TO TimeLimit@). The method - will return null if it cannot find a hypergraph within the branch and time limits. - Example - R = QQ[x_1..x_5]; - randomHyperGraph(R,{3,2,4}) - randomHyperGraph(R,{3,2,4}) - randomHyperGraph(R,{3,2,4}) - randomHyperGraph(R,{4,4,2,2}) -- impossible, returns null when time/branch limit reached - Text - The {\tt randomHyperGraph} method will return null immediately if the sizes of the edges fail to pass - the LYM-inequality: $1/(n choose D_1) + 1/(n choose D_2) + ... + 1/(n choose D_m) \leq 1$ where $n$ is - the number of variables in {\tt R} and $m$ is the length of {\tt D}. Note that even if {\tt D} passes - this inequality, it is not necessarily true that there is some hypergraph with edge sizes given by {\tt D}. - See D. Lubell's "A short proof of Sperner's lemma," J. Combin. Theory, 1:299 (1966). - SeeAlso - randomGraph - randomUniformHyperGraph - BranchLimit - TimeLimit - "Constructor Overview" -/// - ------------------------------------------------------------- --- DOCUMENTATION randomUniformHyperGraph ------------------------------------------------------------- - -doc /// - Key - randomUniformHyperGraph - (randomUniformHyperGraph,PolynomialRing,ZZ,ZZ) - Headline - returns a random uniform hypergraph - Usage - H = randomUniformHyperGraph(R,c,d) - Inputs - R:PolynomialRing - which gives the vertex set of {\tt H} - c:ZZ - the cardinality of the edge sets - d:ZZ - the number of edges in {\tt H} - Outputs - H:HyperGraph - a hypergraph with {\tt d} edges of cardinality {\tt c} on vertex set determined by {\tt R} - Description - Example - R = QQ[x_1..x_9]; - randomUniformHyperGraph(R,3,4) - randomUniformHyperGraph(R,4,2) - SeeAlso - randomGraph - randomHyperGraph - "Constructor Overview" -/// - - ------------------------------------------------------------- --- DOCUMENTATION ring ------------------------------------------------------------- - -doc /// - Key - (ring, HyperGraph) - Headline - gives the ring of a (hyper)graph - Usage - R = ring H - Inputs - H:HyperGraph - Outputs - R:Ring - Description - Text - Every (hyper)graph is defined over some polynomial ring. This method returns the ring of a hypergraph. - Example - S = QQ[a..d]; - g = cycle S; - h = inducedHyperGraph(g,{a,b,c}); - describe ring g - describe ring h - SeeAlso - edges - vertices -/// - - ---------------------------------------------------------- --- DOCUMENTATION simplicialComplexToHyperGraph ----------------------------------------------------------- - - - -doc /// - Key - simplicialComplexToHyperGraph - (simplicialComplexToHyperGraph, SimplicialComplex) - Headline - change the type of a simplicial complex to a (hyper)graph - Usage - H = simplicialComplexToHyperGraph(D) - Inputs - D:SimplicialComplex - the input - Outputs - H:HyperGraph - whose edges are the facets of D - Description - Text - This function takes a simplicial complex and changes it type to a HyperGraph by - returning a hypergraph whose edges are defined by the facets of the simplicial - complex. This is the reverse of the function @TO hyperGraphToSimplicialComplex @ - Example - S = QQ[a..f]; - Delta = simplicialComplex {a*b*c,b*c*d,c*d*e,d*e*f} - H = simplicialComplexToHyperGraph Delta - SeeAlso - hyperGraphToSimplicialComplex - "Constructor Overview" -/// - - ---------------------------------------------------------- --- DOCUMENTATION smallestCycleSize ----------------------------------------------------------- - -doc /// - Key - smallestCycleSize - (smallestCycleSize, Graph) - Headline - returns the size of the smallest induced cycle of a graph - Usage - s = smallestCycleSize(G) - Inputs - G:Graph - the input - Outputs - s:ZZ - the size of the smallest induced cycle - Description - Text - This function returns the size of the smallest induced cycle of a graph. - It is based upon Theorem 2.1 in the paper "Restricting linear syzygies: - algebra and geometry" by Eisenbud, Green, Hulek, and Popsecu. This theorem - states that if G is graph, then the edge ideal of the complement of G satisfies - property N_{2,p}, that is, the resolution of I(G^c) is linear up to the p-th step, - if and only if, the smallest induced cycle of G has length p+3. The algorithm - looks at the resolution of the edge ideal of the complement to determine the size - of the smallest cycle. - Example - T = QQ[x_1..x_9]; - g = graph {x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_5*x_6,x_6*x_7,x_7*x_8,x_8*x_9,x_9*x_1} -- a 9-cycle - smallestCycleSize g - h = graph {x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_5*x_6,x_6*x_7,x_7*x_8,x_8*x_9} -- a tree (no cycles) - smallestCycleSize h - l = graph {x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_5*x_6,x_6*x_7,x_7*x_8,x_8*x_9,x_9*x_1,x_1*x_4} - smallestCycleSize l - Text - Note that if g is a tree if and only if {\tt smallestCycleSize g = 0} -/// - - - ------------------------------------------------------- --- DOCUMENTATION spanningTree ----------------------------------------------------------- - -doc /// - Key - spanningTree - (spanningTree, Graph) - Headline - returns a spanning tree of a graph - Usage - T = spanningTree(G) - Inputs - G:Graph - Outputs - T:Graph - the spanning tree of G - Description - Text - This function returns a breadth first spanning tree of a graph. - Example - R = QQ[x_1..x_6]; - C = cycle R; -- a 6-cycle - spanningTree C - T = graph {x_1*x_2,x_2*x_3, x_1*x_4,x_1*x_5,x_5*x_6}; -- a tree (no cycles) - T == spanningTree T - G = graph {x_1*x_2,x_2*x_3,x_3*x_1,x_4*x_5,x_5*x_6,x_6*x_4}; -- two three cycles - spanningTree G -/// - - - ---------------------------------------------------------- --- DOCUMENTATION vertexCoverNumber ---------------------------------------------------------- - -doc /// - Key - vertexCoverNumber - (vertexCoverNumber, HyperGraph) - Headline - find the vertex covering number of a (hyper)graph - Usage - c = vertexCoverNumber(H) - Inputs - H:HyperGraph - the input - Outputs - c:ZZ - the vertex covering number - Description - Text - This function returns the vertex covering number of a (hyper)graph. The vertex covering number is - the size of smallest vertex cover of the (hyper)graph. This corresponds to the smallest - degree of a generator of the cover ideal of the (hyper)graph. - Example - S = QQ[a..d]; - g = graph {a*b,b*c,c*d,d*a} -- the four cycle - vertexCoverNumber g - S = QQ[a..e]; - g = graph {a*b,a*c,a*d,a*e,b*c,b*d,b*e,c*d,c*e,d*e} -- the complete graph K_5 - vertexCoverNumber g - h = hyperGraph {a*b*c,a*d,c*e,b*d*e} - vertexCoverNumber(h) - SeeAlso - coverIdeal - vertexCovers -/// - - ---------------------------------------------------------- --- DOCUMENTATION vertexCovers ---------------------------------------------------------- - -doc /// - Key - vertexCovers - (vertexCovers, HyperGraph) - Headline - list the minimal vertex covers of a (hyper)graph - Usage - c = vertexCovers(H) - Inputs - H:HyperGraph - the input - Outputs - c:List - of the minimal vertex covers of {\tt H}. The vertex covers are represented as monomials. - Description - Text - This function returns the minimal vertex covers of a (hyper)graph. - A vertex cover is a subset of the vertices such that every edge of the (hyper)graph has - non-empty intersection with this set. The minimal vertex covers are given by the minimal generators - of the cover ideal of {\tt H}. - Example - S = QQ[a..d]; - g = graph {a*b,b*c,c*d,d*a} -- the four cycle - vertexCovers g - coverIdeal g - flatten entries gens coverIdeal g == vertexCovers g - S = QQ[a..e]; - h = hyperGraph {a*b*c,a*d,c*e,b*d*e} - vertexCovers(h) - SeeAlso - coverIdeal - vertexCoverNumber -/// - - ---------------------------------------------------------- --- DOCUMENTATION vertices ---------------------------------------------------------- - -doc /// - Key - vertices - (vertices, HyperGraph) - Headline - gets the vertices of a (hyper)graph - Usage - V = vertices(H) - Inputs - H:HyperGraph - the input - Outputs - V:List - of the vertices of {\tt H} - Description - Text - This function takes a graph or hypergraph and returns the vertex set of the graph. - Example - S = QQ[a..d]; - g = graph {a*b,b*c,c*d,d*a} -- the four cycle - vertices g - h = hyperGraph{a*b*c} - vertices h -- the vertex d is treated as an isolated vertex - SeeAlso - edges -/// - ----------------------------- ---Options documentation----- ----------------------------- - ------------------------------------------------------------- --- DOCUMENTATION Gins ------------------------------------------------------------- - -doc /// - Key - Gins - Headline - optional argument for isSCM - Description - Text - Directs @TO isSCM@ to use generic initial ideals to determine whether the - Alexander dual of the edge ideal of a hypergraph is componentwise linear. See - full discussion at @TO isSCM@. - SeeAlso - isSCM -/// - -doc /// - Key - [isSCM, Gins] - Headline - use gins inside isSCM - Usage - B = isSCM(H,Gins=>true) - Inputs - H:HyperGraph - the hypergraph being considered - Outputs - B:Boolean - whether {\tt H} is SCM or not - Description - Text - The default value for {\tt Gins} is {\tt false} since using generic - initial ideals makes the @TO isSCM@ algorithm probabilistic, and there - are characteristic and monomial order requirements. See full - discussion at @TO isSCM@. - SeeAlso - isSCM -/// - ------------------------------------------------------------- --- DOCUMENTATION BranchLimit ------------------------------------------------------------- - -doc /// - Key - BranchLimit - Headline - optional argument for randomHyperGraph - Description - Text - The @TO randomHyperGraph@ method follows a backtracking algorithm - to generate edges with no inclusions between them. At each step in the - recursive tree, @TO randomHyperGraph@ will make {\tt BranchLimit} attempts to - complete its list of edges. Thus, if a hypergraph with {\tt N} edges is required, - @TO randomHyperGraph@ may take {\tt BranchLimit^N} steps before terminating. - To be more precise, the method is implemented so that it makes {\tt BranchLimit + L} attempts - at level {\tt L} of the recursion. - The default value is 3. - SeeAlso - TimeLimit - randomHyperGraph -/// - -doc /// - Key - [randomHyperGraph, BranchLimit] - Headline - limit recursive branching in randomHyperGraph - Usage - G = randomHyperGraph(R,D,BranchLimit=>n) - Inputs - n:ZZ - number of branches at each level in the recursion of {\tt randomHyperGraph} - Description - Text - The @TO randomHyperGraph@ method follows a backtracking algorithm - to generate edges with no inclusions between them. At each step in the - recursive tree, @TO randomHyperGraph@ will make {\tt BranchLimit} attempts to - complete its list of edges. Thus, if a hypergraph with {\tt N} edges is required, - @TO randomHyperGraph@ may take {\tt BranchLimit^N} steps before terminating. - To be more precise, the method is implemented so that it makes {\tt BranchLimit + L} attempts - at level {\tt L} of the recursion. - The default value is 3. - SeeAlso - TimeLimit - randomHyperGraph -/// - ------------------------------------------------------------- --- DOCUMENTATION MaximalEdges ------------------------------------------------------------- - -doc /// - Key - MaximalEdges - Headline - optional argument for changeRing - Description - Text - This is an option to tell @TO changeRing@ whether to - make a hypergraph using maximal or minimal edges after substitution - for the variables. -/// - -doc /// - Key - [changeRing, MaximalEdges] - Headline - optional argument for changeRing - Usage - G = changeRing(H,R,L,MaximalEdges=>true) - Description - Text - This is an option to tell @TO changeRing@ whether to - make a hypergraph using maximal or minimal edges after substitution - for the variables. -/// - ------------------------------------------------------------- --- DOCUMENTATION OriginalRing ------------------------------------------------------------- - -doc /// - Key - OriginalRing - Headline - optional argument for inducedHyperGraph - Description - Text - This is an option to tell @TO inducedHyperGraph@ whether to return - a hypergraph with the original (larger) ring attached or the subring - only involving the variables of {\tt L}. The smaller ring is the default. - SeeAlso - inducedHyperGraph -/// - -doc /// - Key - [inducedHyperGraph, OriginalRing] - Headline - use OriginalRing inside inducedHyperGraph - Usage - K = inducedHyperGraph(H,L,OrignalRing=>true) - Inputs - H:HyperGraph - the hypergraph being considered - L:List - a list of vertices - Outputs - K:HyperGraph - the induced HyperGraph of {\tt H} on the vertices of {\tt L} - Description - Text - When {\tt OriginalRing} is set to {\tt true}, @TO inducedHyperGraph@ returns - a hypergraph with the original (larger) ring attached rather than the subring - only involving the variables of {\tt L}. - SeeAlso - inducedHyperGraph -/// - ------------------------------------------------------------- --- DOCUMENTATION TimeLimit ------------------------------------------------------------- - -doc /// - Key - TimeLimit - Headline - optional argument for randomHyperGraph - Description - Text - The @TO randomHyperGraph@ method follows a backtracking algorithm - to generate edges with no inclusions between them. As it may take - a long time to terminate, a time limit is imposed on the method. - The {\tt TimeLimit} option is the amount of time, in seconds, that - the method @TO randomHyperGraph@ will take before terminating. - A value of 0 is interpreted as one day. The default value is 5 (seconds). - SeeAlso - BranchLimit - randomHyperGraph -/// - -doc /// - Key - [randomHyperGraph, TimeLimit] - Headline - limit the running time of randomHyperGraph - Usage - randomHyperGraph(R,D,TimeLimit=>s) - Inputs - s:ZZ - time in seconds before randomHyperGraph returns null - Description - Text - The @TO randomHyperGraph@ method follows a backtracking algorithm - to generate edges with no inclusions between them. As it may take - a long time to terminate, a time limit is imposed on the method. - The {\tt TimeLimit} option is the amount of time, in seconds, that - the method @TO randomHyperGraph@ will take before terminating. - A value of 0 is interpreted as one day. The default value is 5 (seconds). - SeeAlso - BranchLimit - randomHyperGraph -/// - ------------------------------ --- Constructor Tests -------- --- Test hyperGraph and Graph ------------------------------ - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(R, {{a,b},{b,c}}) -assert(#(edges H) == 2) -assert(#(vertices H) == 3) -/// - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(R, {{a,b,c}}) -assert(#(edges H) == 1) -assert(#(vertices H) == 3) -/// - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(R, {a*b,b*c}) -assert(#(edges H) == 2) -assert(#(vertices H) == 3) -/// - -TEST/// -R = QQ[a,b,c] -H = hyperGraph({{a,b},{b,c}}) -assert(#(edges H) == 2) -assert(#(vertices H) == 3) -/// - -TEST/// -R = QQ[a,b,c] -H = hyperGraph({a*b,b*c}) -assert(#(edges H) == 2) -assert(#(vertices H) == 3) -/// - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(ideal {a*b,b*c}) -assert(#(edges H) == 2) -assert(#(vertices H) == 3) -/// - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(monomialIdeal {a*b,b*c}) -assert(#(edges H) === 2) -assert(#(vertices H) === 3) -/// - ------------------------------ --- Test Equality == ------------------------------ - -TEST/// -R = QQ[a,b,c,d] -G1 = hyperGraph(R, {{a,b},{b,c}}) -G2 = hyperGraph(R, {{a,b},{b,c}}) -G3 = hyperGraph(R, {{a,b},{c,b}}) -G4 = hyperGraph(R, {{b,c}, {b,a}}) -G5 = hyperGraph(R, {{b,c}, {a,c}}) - -S = QQ[a,b,c] -G6 = hyperGraph(S, {{a,b}, {b,c}}) - -assert(G1 == G1) -assert(G1 == G2) -assert(G1 == G3) -assert(G1 == G4) -assert(G1 != G5) -assert(G1 != G6) -/// - ------------------------------ --- Test adjacencyMatrix ------------------------------ - -TEST/// -R = QQ[a..d] -c4 = graph {a*b,b*c,c*d,d*a} -- 4-cycle plus an isolated vertex!!!! -adjacencyMatrix c4 -m = matrix {{0,1,0,1},{1,0,1,0},{0,1,0,1},{1,0,1,0}} -assert(adjacencyMatrix c4 == m) -/// - ------------------------------ --- Test allEvenHoles ------------------------------ - -TEST/// -R=QQ[a..f] -c4=graph {a*b,b*c,c*d,d*a} -assert (#(allEvenHoles c4)==1) -H=graph(monomialIdeal(a*b,b*c,c*d,d*e,e*f,a*f,a*d)) --6-cycle with a chord -assert (allEvenHoles H == {{a, b, c, d}, {a, d, e, f}}) -/// - ------------------------------ --- Test allOddHoles ------------------------------ - -TEST/// -R=QQ[a..f] -assert (allOddHoles cycle(R,3) == {}) -G=graph(monomialIdeal(a*b,b*c,c*d,d*e,e*f,a*f,a*c)) -assert (allOddHoles G == {{a,c,d,e,f}}) -/// - ----------------------------- --- Test antiCycle ---------------------------- - -TEST/// -S= QQ[a..d] -g = graph {a*c,b*d} -assert(antiCycle(S) == g) -assert(complementGraph antiCycle(S) == cycle(S)) -/// - ------------------------- --- Test changeRing ------------------------- - -TEST/// -P = QQ[a,b,c] -H = hyperGraph {a*b,b*c} -G = hyperGraph {a*b*c} -R = QQ[x,y,z,w] -A1 = hyperGraph {x*z,z*y} -A2 = hyperGraph {x*y} -A3 = hyperGraph {x*y} -A4 = hyperGraph {y} -A5 = hyperGraph {x*y} -A6 = hyperGraph {y} -assert(A1 == changeRing(H,R,{x,z,y})) -assert(A2 == changeRing(G,R,{x,y,y})) -assert(A3 == changeRing(H,R,{x,y,x})) -assert(A4 == changeRing(H,R,{x,y,y})) -assert(A5 == changeRing(H,R,{x,y,y}, MaximalEdges=>true)) -assert(A6 == changeRing(H,R,{x,y,y}, MaximalEdges=>false)) -/// - ------------------------- --- Test chromaticNumber ------------------------- - -TEST/// -R = QQ[a..e] -c4 = graph {a*b,b*c,c*d,d*a} -- 4-cycle -c5 = graph {a*b,b*c,c*d,d*e,e*a} -- 5-cycle -assert(chromaticNumber c4 == 2) -assert(chromaticNumber c5 == 3) -/// - --------------------------- --- Test cliqueComplex and cliqueNumber -------------------------------- - -TEST/// -R=QQ[w,x,y,z] -e = graph {w*x,w*y,x*y,y*z} -- clique on {w,x,y} and {y,z} -Delta1 = cliqueComplex e -- max facets {w,x,y} and {y,z} -Delta2 = simplicialComplex {w*x*y,y*z} -assert(Delta1 === Delta2) -assert(cliqueNumber e -1 == dim Delta1) -/// - ------------------------------ --- Test complementGraph ------------------------------ - -TEST/// -R = QQ[a,b,c,d,e] -c5 = graph {a*b,b*c,c*d,d*e,e*a} -c5c = graph {a*c,a*d,b*d,b*e,c*e} -assert(complementGraph c5 == c5c) -/// - ------------------------------ --- Test completeGraph ------------------------------ - -TEST/// -R = QQ[a,b,c,d] -assert(completeGraph(R) == graph {a*b,a*c,a*d,b*c,b*d,c*d}) -assert(completeGraph(R, 3) == graph {a*b,a*c,b*c}) -/// - ------------------------------ --- Test completeMultiPartite ------------------------------ - -TEST/// -R = QQ[a,b,c,d] -assert(completeMultiPartite(R, 2,2) == graph {a*d,a*c,b*c,b*d}) -assert(completeMultiPartite(R, {1,3}) == graph {a*b,a*c,a*d}) -assert(completeMultiPartite(R, {{b},{a,c,d}}) == graph {b*a,b*c,b*d}) -/// - ------------------------------ --- Test connectedComponents ------------------------------ - -TEST/// -R = QQ[a..k] -H = hyperGraph {a*b, c*d*e,e*k, b*f, g, f*i} -assert(# connectedComponents(H) == 3 ) -R = QQ[a,b,c,d] -G = hyperGraph {a*b*c} -H = hyperGraph {a,b,c} -assert(# connectedComponents(G) == 1 ) -assert(# connectedComponents(H) == 3 ) -/// - ------------------------------ --- Test coverIdeal ------------------------------ - -TEST/// -R = QQ[a,b,c] -i = monomialIdeal {a*b,b*c} -j = monomialIdeal {b,a*c} -h = hyperGraph i -assert((coverIdeal h) == j) -/// - ------------------------------ --- Test cycle ------------------------------ - -TEST/// -R = QQ[a..d] -G = graph(monomialIdeal(a*b,b*c,c*d,a*d)) -assert (G == cycle(R,4)) -/// - ------------------------------ --- Test degreeVertex ------------------------------ - -TEST/// -R = QQ[a,b,c,d] -H = hyperGraph(monomialIdeal {a*b,b*c,c*d,c*a}) -assert( degreeVertex(H,a) == 2) -assert( degreeVertex(H,0) == 2) -assert( degreeVertex(H,b) == 2) -assert( degreeVertex(H,1) == 2) -assert( degreeVertex(H,c) == 3) -assert( degreeVertex(H,2) == 3) -assert( degreeVertex(H,d) == 1) -assert( degreeVertex(H,3) == 1) -/// - ------------------------------ --- Test deleteEdges ------------------------------ - -TEST/// -R = QQ[a..d] -G = deleteEdges(completeGraph R,{{b,d},{a,c}}) -assert (G == graph(monomialIdeal(a*b,a*d,b*c,c*d))) -/// - ------------------------------ --- Test edgeIdeal ------------------------------ - -TEST/// -R = QQ[a,b,c] -i = monomialIdeal {a*b,b*c} -h = hyperGraph i -assert((edgeIdeal h) == i) -/// - ------------------------------ --- Test edges ------------------------------ - -TEST/// -R = QQ[a..d] -G = graph(monomialIdeal(a*b,c*d,a*d)) -assert (edges G == {{a,b},{a,d},{c,d}}) -/// - ------------------------------ --- Test getCliques --- Test getMaxCliques ------------------------------ - -TEST/// -R = QQ[a..d] -G = completeGraph R -assert (getMaxCliques G == {{a,b,c,d}}) -assert (#(getCliques G) == binomial(4,2)+binomial(4,3)+binomial(4,4)) -/// - ------------------------------ --- Test getEdge ------------------------------ -TEST/// -R = QQ[a..d] -H = hyperGraph(R,{{a,b,d},{d,c,b}}) -assert (getEdge(H,0) == {a,b,d}) -/// - ------------------------------ --- Test getEdgeIndex ------------------------------ - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(monomialIdeal {a*b,b*c}) -assert( getEdgeIndex(H,{a,b}) == 0) -assert( getEdgeIndex(H,a*b) == 0) -assert( getEdgeIndex(H,{c,b}) == 1) -assert( getEdgeIndex(H,c*b) == 1) -assert( getEdgeIndex(H,{a,c}) == -1) -assert( getEdgeIndex(H,a*c) == -1) -/// - ------------------------------ --- Test getGoodLeaf --- Test getGoodLeafIndex --- Test hasGoodLeaf --- Test isGoodLeaf ------------------------------ - -TEST/// -R = QQ[a..g] -H = hyperGraph {a*b*c*d,b*c*d*e,c*d*f,d*g,e*f*g} -G = hyperGraph {b*c*d*e,d*g,e*f*g,a*b*c*d} -C = graph {a*b,b*c,c*d,d*e,e*a} -- 5-cycle -assert( getGoodLeaf(H) === {a,b,c,d}) -assert( getGoodLeafIndex(H) === getEdgeIndex(H, {a,b,c,d})) -assert( getGoodLeaf(G) === {a,b,c,d}) -assert( hasGoodLeaf G ) -assert( isGoodLeaf(H, getEdgeIndex(H,{a,b,c,d})) ) -assert( not isGoodLeaf(H, getEdgeIndex(H,{b,c,d,e})) ) -assert( not hasGoodLeaf C ) -/// - ------------------------------ --- Test hasOddHole --- Test isPerfect ------------------------------ - -TEST/// -R = QQ[a..g] -G = graph {a*b,b*c,c*d,d*e,e*f,f*g,a*g} -H = complementGraph G -assert hasOddHole G -assert not hasOddHole H -assert not isPerfect G -/// - ------------------------------ --- Test hyperGraphToSimplicialComplex ----------------------------------- - -TEST/// -R = QQ[x_1..x_6] -G = graph({x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_1*x_5,x_1*x_6,x_5*x_6}) --5-cycle and a triangle -DeltaG = hyperGraphToSimplicialComplex G -hyperGraphDeltaG = simplicialComplexToHyperGraph DeltaG -GPrime = graph(hyperGraphDeltaG) -assert(G === GPrime) -/// - ------------------------------ --- Test incidenceMatrix ------------------------------ - -TEST/// -R = QQ[a..f] -H = hyperGraph {a*b*c*d,c*d*e,f} -assert(incidenceMatrix H == matrix {{1,0,0},{1,0,0},{1,1,0},{1,1,0},{0,1,0},{0,0,1}}) -/// - ------------------------------------ --- Test independenceComplex ------------------------------------ - -TEST/// -R = QQ[a..e] -c5 = graph {a*b,b*c,c*d,d*e,e*a} -D = simplicialComplex monomialIdeal (a*b,b*c,c*d,d*e,e*a) -assert(D === independenceComplex c5) -/// - - ------------------------------ --- Test independenceNumber ------------------------------ - -TEST/// -R = QQ[a..e] -c4 = graph {a*b,b*c,c*d,d*a} -- 4-cycle plus an isolated vertex!!!! -c5 = graph {a*b,b*c,c*d,d*e,e*a} -- 5-cycle -assert(independenceNumber c4 == 3) -assert(independenceNumber c5 == 2) -/// - ------------------------------ --- Test inducedHyperGraph ------------------------------ - -TEST/// -R = QQ[a..e] -G = graph {a*b,b*c,c*d,d*e,a*e} -assert(inducedHyperGraph(G,{a,d,e},OriginalRing=>true)==graph(monomialIdeal(d*e,a*e))) -H = inducedHyperGraph(G,{a,d,e}) -use ring H -assert(H == hyperGraph(monomialIdeal(d*e,a*e))) -/// - ------------------------------ --- Test isBipartite ------------------------------ - -TEST/// -R = QQ[a..e] -c4 = graph {a*b,b*c,c*d,d*a} -- 4-cycle -c5 = graph {a*b,b*c,c*d,d*e,e*a} -- 5-cycle -assert(isBipartite c4 == true) -assert(isBipartite c5 == false) -/// - - ------------------------------------ --- Test isChordal ----------------------------------- - -TEST/// -R = QQ[a..e]; -C = cycle R; -assert(isChordal C == false) -D = graph {a*b,b*c,c*d,a*c} -assert(isChordal D == true) -assert((isChordal completeGraph (QQ[a..e])) == true) -/// - ------------------------------ --- Test isCM ------------------------------ - -TEST/// -R = QQ[a..e]; -C = cycle R; -UnmixedTree = graph {a*b, b*c, c*d}; -MixedTree = graph {a*b, a*c, a*d}; -assert isCM C -assert isCM UnmixedTree -assert not isCM MixedTree -/// - ------------------------------ --- Test isConnected ------------------------------ - -TEST/// -S = QQ[a..e] -g = graph {a*b,b*c,c*d,d*e,a*e} -- the 5-cycle (connected) -h = graph {a*b,b*c,c*a,d*e} -- a 3-cycle and a disjoint edge (not connected) -assert(isConnected g) -assert(not isConnected h) -/// - ------------------------------ --- Test isEdge ------------------------------ - -TEST/// -R = QQ[a,b,c] -H = hyperGraph(monomialIdeal {a*b,b*c}) -assert( isEdge(H,{a,b}) ) -assert( isEdge(H,a*b) ) -assert( isEdge(H,{c,b}) ) -assert( isEdge(H,b*c) ) -assert( not isEdge(H,{a,c}) ) -assert( not isEdge(H,a*c) ) -/// - ------------------------------ --- Test isForest ------------------------------ - -TEST/// -R = QQ[a..h] -H = hyperGraph {a*b*h, b*c*d, d*e*f, f*g*h, b*d*h*f} -K = hyperGraph {a*b*h, b*c*d, d*e*f, b*d*h*f} -G = graph {a*b,b*c,b*d,d*e, f*g, g*h} -J = graph {a*b,b*c,b*d,d*e, f*g, g*h, e*a} -assert( not isForest H ) -assert( isForest K ) -assert( isForest G ) -assert( not isForest J ) -assert( isForest hyperGraph G ) -assert( not isForest hyperGraph J ) -/// - ------------------------------ --- Test isLeaf ------------------------------ - -TEST/// -R = QQ[a..e] -G = graph {a*b,b*c,c*d,d*a,a*e} -H = hyperGraph {a*b*c,b*d,c*e} -I = hyperGraph {a*b*c,b*c*d,c*e} -assert(isLeaf(G,4)) -assert(not isLeaf(G,1)) -assert(not isLeaf(G,0)) -assert(not isLeaf(G,a)) -assert(isLeaf(G,e)) -assert(not isLeaf(H,0)) -assert(isLeaf(I,0)) -/// - ------------------------------ --- Test lineGraph ------------------------------ - -TEST/// -R = QQ[a..e] -G = graph {a*b,a*c,a*d,d*e} -assert(adjacencyMatrix lineGraph G == matrix {{0,1,1,0},{1,0,1,0},{1,1,0,1},{0,0,1,0}}) -/// - ------------------------------ --- Test neighbors ------------------------------ - -TEST/// -S = QQ[a..f] -G = graph {a*b,a*c,a*d,d*e,d*f} -assert(apply(gens S, V -> #neighbors(G, V)) == {3,1,1,3,1,1}) -assert(apply(numgens S, N -> #neighbors(G, N)) == {3,1,1,3,1,1}) -assert(neighbors(G, {a,c}) == {b,d}) -assert(neighbors(G, {e,f}) == {d}) -/// - - ------------------------------ --- Test numConnectedComponents ------------------------------ -TEST/// -S = QQ[a..e] -g = graph {a*b,b*c,c*d,d*e,a*e} -- the 5-cycle (connected) -h = graph {a*b,b*c,c*a,d*e} -- a 3-cycle and a disjoint edge (not connected) -assert(numConnectedComponents g == 1) -assert(numConnectedComponents h == 2) -/// - -------------------------------------- --- Test randomGraph -------------------------------------- - -TEST/// -R = QQ[a..e] -G = randomGraph(R,3) -assert(#(edges G) == 3) -assert(vertices G == {a,b,c,d,e}) -/// - -------------------------------------- --- Test randomUniformHyperGraph -------------------------------------- - -TEST/// -R = QQ[a..e] -G = randomUniformHyperGraph(R,3,2) -assert(#(edges G)==2) -assert(#(first edges G)==3) -/// - -------------------------------------- --- Test ring -------------------------------------- - -TEST/// -S = QQ[a..e] -G = graph monomialIdeal(a*b,c*e) -assert(ring G === S) -H = hyperGraph(S,{{a,b,c},{a,d}}) -assert(ring H === S) -/// - -------------------------------------- --- Test simplicialComplexToHyperGraph -------------------------------------- - -TEST/// -S = QQ[a..f] -Delta = simplicialComplex {a*b*c,b*c*d,c*d*e,d*e*f} -h = simplicialComplexToHyperGraph Delta -assert(class h === HyperGraph) -/// - ------------------------------ --- Test smallestCycleSize ------------------------------ - -TEST/// -T = QQ[x_1..x_9] -g = graph {x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_5*x_6,x_6*x_7,x_7*x_8,x_8*x_9,x_9*x_1} -- a 9-cycle -assert(smallestCycleSize g == 9) -/// - --------------------------------- --- Test spanningTree ------------------------------- -TEST/// -T = QQ[x_1..x_9] -h = graph {x_1*x_2,x_2*x_3,x_3*x_4,x_4*x_5,x_5*x_6,x_6*x_7,x_7*x_8,x_8*x_9} -- a tree (no cycles) -assert(spanningTree h === h) -/// - ------------------------------ --- Test vertexCoverNumber ------------------------------ -TEST/// -S = QQ[a..d] -g = graph {a*b,b*c,c*d,d*a} -- the four cycle -assert(vertexCoverNumber g == 2) -/// - ------------------------------ --- Test vertexCovers ------------------------------ -TEST/// -S = QQ[a..d] -g = graph {a*b,b*c,c*d,d*a} -- the four cycle -vertexCovers g -coverIdeal g -assert(flatten entries gens coverIdeal g == vertexCovers g) -/// - ------------------------------ --- Test vertices ------------------------------ - -TEST/// -R = QQ[a..f] -G = graph {a*b,b*c,c*d,d*e,e*f} -V = vertices(G) -assert(vertices(G) == {a,b,c,d,e,f}) -/// - -end - ---restart ---installPackage ("EdgeIdeals", UserMode=>true) ---loadPackage "EdgeIdeals" ---viewHelp - diff --git a/M2/Macaulay2/packages/supplanted-packages/PieriMaps.m2 b/M2/Macaulay2/packages/supplanted-packages/PieriMaps.m2 deleted file mode 100644 index 03a6837171c..00000000000 --- a/M2/Macaulay2/packages/supplanted-packages/PieriMaps.m2 +++ /dev/null @@ -1,586 +0,0 @@ --- -*- coding: utf-8 -*- -newPackage( - "PieriMaps", - Version => "1.0", - Date => "July 3, 2009", - Authors => {{ - Name => "Steven V Sam", - Email => "ssam@math.mit.edu", - HomePage => "http://math.mit.edu/~ssam/" - }}, - Headline => "computations of matrices between representations of - the general linear group based on the Pieri formulas", - DebuggingMode => false - ) - -export({straighten, standardTableaux, pieri, pureFree, schurRank}) - --------------------------------- --- subroutines (not exported) -- --------------------------------- - --- All matrices computed are in terms of the ordered bases given by --- standardTableaux - --- Input: --- List L --- Output: --- True if L is weakly decreasing, false otherwise -isDecreasing = L -> ( - for i from 0 to #L-2 do if L#i < L#(i+1) then return false; - true - ) - --- Input: --- List L --- Output: --- True if L is strictly increasing, false otherwise -isIncreasing = L -> ( - for i from 0 to #L-2 do if L#i >= L#(i+1) then return false; - true - ) - --- Input: --- List T: a tableau, e.g., {{0,1,2},{2,3}} --- Output: --- If T not standard (weakly increasing rows, increasing columns), return --- first violating entry (starting from bottom to top, left to right); --- otherwise return null -isStandard = T -> ( - i := #T-2; - while i >= 0 do ( - a := T#i; - b := T#(i+1); - n := #b; - for j from 0 to n-1 do if a#j >= b#j then return (i,j); - i = i-1; - ); - null - ) - --- Input: --- List T: a tableau --- Integer col: specify a column --- Integer row{1,2}, specify two rows --- Output: --- Take all entries in row1 from column col to the end and all entries in --- row2 from beginning to col, and return all possible permutations of these --- entries (ignoring that some entries might be equal). The output is given in --- the form a hash table where the keys are the resulting tableau and the --- values are -1 -shuffle = (T, col, row1, row2) -> ( - len1 := #(T#row1); - len2 := #(T#row2); - truncatedrow1 := (T#row1)_{0..col-2}; -- grab row1 entries - truncatedrow2 := (T#row2)_{col..len2-1}; -- grab row2 entries - L := join((T#row1)_{col-1..len1-1}, (T#row2)_{0..col-1}); - P := permutations L; - output := {}; - P = apply(P, i-> (for j from 0 to #T-1 list ( - if j == row1 then sort join(truncatedrow1, i_{0..len1-col}) - else if j == row2 then sort join(i_{len1-col+1..#i-1}, truncatedrow2) - else T#j))); - coeff := 0; - for i in P do if i == T then coeff = coeff + 1; - for i in P do if i != T then output = append(output, (i, -1 / coeff)); - return hashTable(plus, output); - ) - --- Input: --- List T: a tableau --- Output: --- Writes T as a linear combination of other tableaux T' s.t. T' ( - x := isStandard T; - if x === null then return new HashTable from {T=>1}; - H := new MutableHashTable from shuffle(T, x#1+1, x#0, x#0+1); - if H #? T then ( - coeff := -(H#T) + 1; - remove(H,T); - prehash := {}; - for i in keys H do - prehash = append(prehash, (i, H#i / coeff)); - return hashTable(prehash) - ) - else return new HashTable from H - ) - --- The following functions are based on the Olver map defined in --- Andrzej Daszkiewicz, ``On the Invariant Ideals of the Symmetric --- Algebra S. (V \oplus \wedge^2 V)'' --- The notation used is taken from there - --- Input: --- List mu: a partition --- ZZ k: an index --- Output: --- Subtract one from the kth (in human count, not computer count) row of mu -subtractOne = (mu, k) -> ( - result := {}; - for i from 0 to #mu-1 when true do - if i == k-1 then result = append(result, mu_i - 1) - else result = append(result, mu_i); - return result - ) - -------------------- --- Main routines -- -------------------- - --- Returns dual partition -dualPart = method() -dualPart(List) := mu -> ( - result := {}; - for i from 1 to mu#0 when true do ( - counter := 0; - for j from 0 to #mu-1 when true do if mu#j >= i then counter = counter + 1; - result = append(result, counter); - ); - return result; - ) - --- Computes the dimension of S_mu V where V has dimension n and --- S_mu is the Schur functor associated to mu -schurRank = method() -schurRank(ZZ, List) := (n, mu) -> ( - M := mu; - if #M < n then M = mu|toList(n-#M:0); - det map(ZZ^n, ZZ^n, (i,j) -> binomial(M_i + n - 1 - i + j, n-1)) - ) - --- Input: --- Integer dim: number of labels to be used --- List mu: a partition --- Output: --- All standard tableaux of shape mu and with labels from 0..dim-1 -standardTableaux = method() -standardTableaux(ZZ, List) := (dim, mu) -> ( - if #mu == 0 then return {{}}; - output := {}; - otherrows := standardTableaux(dim, remove(mu, 0)); - firstrow := rsort compositions(dim, mu#0); - for i in firstrow do ( - temp := {}; - for j from 0 to #i-1 do - for k from 1 to i#j when true do - temp = append(temp,j); - for j in otherrows do ( - temp2 := prepend(temp,j); - if isStandard(temp2) === null then - output = append(output, temp2); - ); - ); - return output - ) - --- Input: --- List t: a tableau --- MutableHashTable h: a hash table which memoizes recursive calls and --- stores the coefficients of the straightening of t into standard tableaux -straighten = method() -straighten(List) := t -> ( - t = apply(t, i->sort(i)); - h := new MutableHashTable from {}; - straighten(t, h); - h#t - ) - -straighten(List, MutableHashTable) := (t, h) -> ( - t = apply(t, i -> sort i); - if h #? t then return null; - if isStandard(t) === null then - h#t = new HashTable from {t => 1}; - - firstIter := towardStandard(t); - H := hashTable({}); -- straightening of t - for i in keys firstIter do ( - coeff := firstIter#i; - straighten(i, h); - temp := {}; - for j in keys h#i do temp = append(temp, (j, coeff * (h#i)#j)); - H = merge(H, hashTable(temp), plus); - temp = {}; - for j in keys H do if H#j != 0 then temp = append(temp,(j,H#j)); - H = hashTable(temp); - ); - h#t = H; - return null; - ) - --- Input: --- List mu: A partition --- ZZ k: a number specifying which row to remove a box from mu --- PolynomialRing P: the coefficient ring for the Pieri map over a field K --- Output: --- An GL(n,K)-equivariant map P \otimes S_mu K^n -> P \otimes S_lambda K^n --- where lambda is mu with a box removed from the kth row, and S_mu denotes --- the Schur functor associated to mu -pieriHelper = method() -pieriHelper(List, ZZ, PolynomialRing) := (mu, k, P) -> ( - d := numgens P; - X := gens P; - output := {}; - Sbasis := standardTableaux(d, mu); - Tbasis := standardTableaux(d, subtractOne(mu, k)); - mu = prepend(0,mu); - A := {}; - for p from 0 to k when true do A = join(A, apply(subsets(1..(k-1), p), s -> prepend(0, append(s, k)))); - for s in apply(Sbasis, i->prepend({},i)) do ( - row := {}; - H := new HashTable from {}; - for J in A do ( - cJ := 1; - for q from 1 to #J-2 when true do cJ = cJ * (mu_(J_q) - mu_k + k - J_q); - h := hashTable({(s, (-1)^#J / cJ)}); - for i from 0 to #J-2 when true do ( - temp := {}; - for T in keys h do ( - for b from 0 to #(T_(J_(i+1)))-1 when true do ( - U := new MutableList from T; - U#(J_(i+1)) = remove(U#(J_(i+1)), b); - U#(J_i) = append(U#(J_i), (T_(J_(i+1)))_b); - temp = append(temp, (new List from U, h#T)); - ); - ); - h = hashTable(plus, temp); - ); - H = merge(H, h, plus); - ); - H = new MutableHashTable from H; - memo := new MutableHashTable from {}; - for T in keys H do ( - U := apply(remove(T,0), i->sort(i)); - coeff := H#T; - remove(H, T); - straighten(U, memo); - for i in keys memo#U do - if H #? i then H#i = H#i + coeff * (memo#U)#i * X_((T_0)_0) - else H#i = coeff * (memo#U)#i * X_((T_0)_0); - ); - for t in Tbasis do if H #? t then row = append(row, H#t) else row = append(row, 0); - output = append(output, row); - ); - return map(P^(#Tbasis), P^{#Sbasis:-1}, transpose output); - ) - --- Input: --- List mu: A partition --- List boxes: A list of numbers which specifies the rows that boxes are to be --- removed from mu --- PolynomialRing P: a polynomial ring over a field K with n generators --- Output: --- A GL(V)-equivariant map P \otimes S_mu V -> P \otimes S_lambda V, where --- S_mu denotes the Schur functor associated to mu, and lambda is the --- partition obtained from mu by deleting boxes_0, boxes_1, ..., in order. -pieri = method() -pieri(List, List, PolynomialRing) := (mu, boxes, P) -> ( - -- check if row indices are okay - for i in boxes do if i < 1 or i > #mu then error "The second argument must specify row indices of the partition in the first argument."; - -- check if removal of boxes gives a partition - lambda := mu; - for i in boxes do ( - lambda = subtractOne(lambda, i); - if not isDecreasing(lambda) then error "The second argument needs to specify a horizontal strip in the first argument."; - ); - -- check if mu/lambda is a horizontal strip - for i from 0 to #mu-2 do - if lambda#i < mu#(i+1) then error "The second argument needs to specify a horizontal strip in the first argument."; - -- error checking done - if char P == 0 then pierizero(mu, boxes, P) - else pierip(mu, boxes, P) - ) - -pierizero = method() -pierizero(List, List, PolynomialRing) := (mu, boxes, P) -> ( - R := coefficientRing(P); - d := numgens(P); - result := pieriHelper(mu, boxes#0, P); - for b from 1 to #boxes-1 do ( - mu = subtractOne(mu, boxes#(b-1)); - result = pieriHelper(mu, boxes#b, P) * result; - ); - return result; - ) - -pierip = method() -pierip(List, List, PolynomialRing) := (mu, boxes, P) -> ( - X := gens(P); - d := numgens(P); - R := QQ[X]; - f := pierizero(mu, boxes, R); - mon := apply(compositions(d, #boxes), i-> (output := 1; for j from 0 to #i-1 do output = output * X_j^(i#j); output)); - result := {}; - denom := 1; - for i from 0 to (rank source f)-1 do ( - row := flatten entries f_{i}; - newrow := {}; - for j from 0 to #row-1 do - for k in mon do ( - coeff := coefficient(k, row#j); - temp := ceiling(1 / gcd(coeff, 1)); - denom = denom * temp / gcd(denom, temp); - newrow = append(newrow, coeff); - ); - result = append(result, newrow); - ); - result2 := {}; - for i in result do - result2 = append(result2, apply(i, j -> round(j*denom))); - intmat := map(ZZ^((rank target f) * #mon), ZZ^(rank source f), transpose(result2)); - (D, S, T) := smithNormalForm(intmat); - S' := (S^(-1))_{0..(rank source D)-1}; - ((id_(P^((rank target S') // #mon))) ** matrix {mon}) * (P ** S') - ) - --- Input: --- List d: a degree sequence --- Module V: A vector space over a field k of characteristic 0 --- Output: --- An inclusion of GL(V)-representations whose graded minimal resolution is pure --- with degree sequence d -pureFree = method() -pureFree(List, PolynomialRing) := (d, P) -> ( - if not isIncreasing(d) then error "The first argument needs to be a strictly increasing list of degrees."; - e := {}; - for i from 1 to #d-1 do e = append(e, d#i - d#(i-1)); - counter := -#e + 1; - for i in e do counter = counter + i; - lambda := {counter - e#0}; - for i from 1 to #e-1 do - lambda = append(lambda, lambda#(i-1) - e#i + 1); - lambda = prepend(counter, remove(lambda, 0)); - pieri(lambda, toList(e#0 : 1), P) ** P^{-d#0} - ) - -------------------- --- Documentation -- -------------------- - -beginDocumentation() -document { - Key => PieriMaps, - Headline => "Methods for computing Pieri inclusions", - "For mathematical background of this package and some examples of use, see:", - BR{}, - "Steven V Sam, Computing inclusions of Schur modules, arXiv:0810.4666", - BR{}, - "Some other references:", - BR{}, - "Andrzej Daszkiewicz, On the Invariant Ideals of the Symmetric Algebra $S.(V \\oplus \\wedge^2 V)$, J. Algebra 125, 1989, 444-473.", - BR{}, - "David Eisenbud, Gunnar Fl\\o ystad, and Jerzy Weyman, The existence of pure free resolutions, arXiv:0709.1529.", - BR{}, - "William Fulton, Young Tableaux: With Applications to Representation Theory and Geometry, London Math. Society Student Texts 35, 1997.", - BR{}, - "Jerzy Weyman, Cohomology of Vector Bundles and Syzygies, Cambridge University Press, 2002.", - BR{}, - BR{}, - "Let V be a vector space over K. If K has characteristic 0, then - given the partition mu and the partition mu' obtained from mu by - removing a single box, there is a unique (up to nonzero scalar) - GL(V)-equivariant inclusion S_mu V -> V otimes S_mu' V, where - S_mu refers to the irreducible representation of GL(V) with - highest weight mu. This can be extended uniquely to a map of P = - Sym(V)-modules P otimes S_mu V -> P otimes S_mu' V. The purpose - of this package is to write down matrix representatives for these - maps. The main function for doing so is ", - TO pieri, - ". Here is an example of the use of the package PieriMaps, which is also - designed to check whether the maps are being constructed correctly - (important, since it is notoriously difficult to get the signs and - coefficients right.) ", - "We will construct by hand the free resolution in 3 variables corresponding - to the degree sequence (0,2,3,6). Let's start with the packaged code:", - EXAMPLE lines /// - R = QQ[a,b,c]; - f = pureFree({0,2,3,6}, R) - betti res coker f - ///, - "By the general theory from Eisenbud-Fl\\o ystad-Weyman, each of these free - modules should be essentially Schur functors corresponding to the - following partitions.", - EXAMPLE lines /// - schurRing(s,3) - dim s_{2,2} - dim s_{4,2} - dim s_{4,3} - dim s_{4,3,3} - ///, - "This package also provides a routine ", - TO schurRank, - " for computing this dimension:", - EXAMPLE lines /// - schurRank(3, {2,2}) - schurRank(3, {4,2}) - schurRank(3, {4,3}) - schurRank(3, {4,3,3}) - ///, - "We now use ", - TO pieri, - " to construct each of the maps of the resolution separately.", - EXAMPLE lines /// - f1 = pieri({4,2,0},{1,1}, R) - f2 = pieri({4,3,0},{2}, R) - f3 = pieri({4,3,3},{3,3,3}, R) - ///, - "Fix the degrees (i.e. make sure that the target of f2 is the source of f1, - etc). Otherwise the test of exactness below would fail.", - EXAMPLE lines /// - f1 - f2 = map(source f1,,f2) - f3 = map(source f2,,f3) - f1 * f2 - f2 * f3 - ///, - "Check that the complex is exact.", - EXAMPLE lines /// - ker f1 == image f2 - ker f2 == image f3 - ///, - "Looks great! Now let's try it modulo some prime numbers and see if we get exactness.", - EXAMPLE lines /// - p = 32003 - R = ZZ/p[a,b,c]; - f1 = pieri({4,2,0},{1,1},R) - betti res coker f1 - f2 = pieri({4,3,0},{2},R) - f3 = pieri({4,3,3},{3,3,3},R) - f2 = map(source f1,,f2) - f3 = map(source f2,,f3) - f1 * f2 - f2 * f3 - ker f1 == image f2 - ker f2 == image f3 - ///, - "These do not piece together well. The reason is that ", - TO pieri, - " changes the bases of the free modules in a way which is not invertible - (over ZZ) when the ground field has positive characteristic.", - SeeAlso => {pieri, pureFree, schurRank} - } - -document { - Key => {standardTableaux, (standardTableaux, ZZ, List)}, - Headline => "list all standard tableaux of a certain shape with bounded labels", - SeeAlso => schurRank, - Usage => "standardTableaux(dim, mu)", - Inputs => { - "dim" => {ofClass ZZ, ", number of labels to be used"}, - "mu" => {ofClass List, ", a partition which gives the shape"} - }, - Outputs => { - List => {"list of all standard tableaux of shape mu with labels 0,...,dim-1"} - }, - EXAMPLE lines /// - standardTableaux(3, {2,2}) -- lists all standard tableaux on the 2x2 square with entries 0,1,2 - /// - } - -document { - Key => {straighten, (straighten, List), (straighten, List, MutableHashTable)}, - Headline => "computes straightening of a tableau", - Usage => concatenate("straighten(t)", "straighten(t, h)"), - Inputs => { - "t" => {ofClass List, ", a tableau to straighten; a tableau looks like {{3,4}, {1,2}} for example, where we list the entries from left to right, top to bottom"}, - "h" => {ofClass MutableHashTable, ", where the answers should be stored"} - }, - Consequences => { "If provided, the hashtable h is updated with any calculations which are performed as a result of calling this function. " }, - "If a hashtable h is provided, then this outputs nothing, it simply just modifies h. When looking up values, remember that the keys are stored with rows weakly increasing. ", - "If no hashtable is provided, then the user is simply given the straightening of the tableau in terms of semistandard tableaux. ", - "The answer is in the form a hashtable: each key is a semistandard tableaux, and the value of the key is the coefficient of that semistandard tableaux used to write the input t as a linear combination. ", - EXAMPLE lines /// - h = new MutableHashTable from {} - straighten({{3,4}, {1,2}}, h) - h#{{3,4}, {1,2}} -- get the coefficients - straighten({{3,4}, {1,2}}) -- just get the answer instead - /// - } - -document { - Key => {pieri, (pieri, List, List, PolynomialRing)}, - Headline => "computes a matrix representation for a Pieri inclusion of representations of a general linear group", - SeeAlso => {pureFree}, - Usage => "pieri(mu, boxes, P)", - Inputs => { - "mu" => {ofClass List, ", a partition (mu_1, ..., mu_r) where mu_i is the number of boxes in the ith row"}, - "boxes" => {ofClass List, ", a list of rows from which to remove boxes (boxes are always removed from the end of the row). This specifies which map of GL(V) representations we want. The row indices start from 1 and not 0, and this must specify a horizontal strip in mu (see description below). "}, - "P" => {ofClass PolynomialRing, ", a polynomial ring over a field K in n variables" } - }, - Outputs => { - Matrix => {"If K has characteristic 0, then given the partition mu and the partition mu' obtained from mu by removing a single box, - there is a unique (up to nonzero scalar) GL(V)-equivariant inclusion S_mu V -> V otimes S_mu' V, where S_mu refers to the - irreducible representation of GL(V) with highest weight mu. This can be extended uniquely to a map of P = Sym(V)-modules - P otimes S_mu V -> P otimes S_mu' V. This method computes the matrix representation for the composition of maps that one obtains by - iterating this procedure of removing boxes, i.e., the final output is a GL(V)-equivariant map P otimes S_mu V -> P otimes S_lambda V - where lambda is the partition obtained from mu by deleting a box from row boxes_0, a box from row boxes_1, etc. - If K has positive characteristic, then the corresponding map is calculated over QQ, lifted to a ZZ-form of the representation which has - the property that the map has a torsion-free cokernel over ZZ, and then the coefficients are reduced to K." - } - }, - "Convention: the partition (d) represents the dth symmetric power, while the partition (1,...,1) represents the dth exterior power. ", - "Using the notation from the output, mu/lambda must be a horizontal strip. Precisely, this means that lambda_i >= mu_(i+1) for all i. - If this condition is not satisfied, the program throws an error because a nonzero equivariant map of the desired form will not exist. ", - EXAMPLE lines /// - pieri({3,1}, {1}, QQ[a,b,c]) -- removes the last box from row 1 of the partition {3,1} - res coker oo -- resolve this map - betti oo -- check that the resolution is pure - /// - } - -document { - Key => {pureFree, (pureFree, List, PolynomialRing)}, - Headline => "computes a GL(V)-equivariant map whose resolution is pure, or the reduction mod p of such a map", - SeeAlso => {pieri}, - Usage => "pureFree(d, P)", - Inputs => { - "d" => {ofClass List, ", a list of degrees (increasing numbers)"}, - "P" => {ofClass PolynomialRing, ", a polynomial ring over a field K in n variables" } - }, - Outputs => { - Matrix => {"A map whose cokernel has Betti diagram with degree sequence d if K has characteristic 0. - If K has positive characteristic p, then the corresponding map is calculated over QQ and is lifted to a ZZ-form which is then reduced mod p." } - }, - "The function translates the data of a degree sequence d for a desired pure free resolution into the data of a Pieri map - according to the formula of Eisenbud-Fl\\o ystad-Weyman and then applies the function ", - TO pieri, - ".", - EXAMPLE lines /// - betti res coker pureFree({0,1,2,4}, QQ[a,b,c]) -- degree sequence {0,1,2,4} - betti res coker pureFree({0,1,2,4}, ZZ/2[a,b,c]) -- same map, but reduced mod 2 - betti res coker pureFree({0,1,2,4}, GF(4)[a,b,c]) -- can also use non prime fields - /// - } - -document { - Key => {schurRank, (schurRank, ZZ, List)}, - Headline => "computes the dimension of the irreducible GL(QQ^n) representation associated to a partition", - SeeAlso => standardTableaux, - Usage => "schurRank(n, mu)", - Inputs => { - "n" => {ofClass ZZ, ", the size of the matrix group GL(QQ^n)"}, - "mu" => {ofClass List, ", a partition (mu_1, ..., m_r) where mu_i is the number of boxes in the ith row"} - }, - Outputs => { - ZZ => {"The dimension of the irreducible GL(QQ^n) representation associated to mu"} - }, - "The dimension is computed using the determinantal formula given by the Weyl character formula.", - EXAMPLE lines /// - schurRank(5, {4,3}) -- should be 560 - /// - } - -TEST /// -t = new BettiTally from {(0,{0},0)=>8, (1,{1},1) =>15, (2,{3},3)=>10, (3,{5},5)=>3}; -assert (t == betti res coker pieri({3,1},{1},QQ[a,b,c])) -t = new BettiTally from {(0,{0},0)=>15, (1,{1},1) =>24, (2,{4},4)=>15, (3,{6},6)=>6}; -assert (t == betti res coker pieri({4,1},{1},QQ[a,b,c])) -t = new BettiTally from {(0,{0},0)=>20, (1,{2},2) =>60, (2,{3},3)=>64, (3,{4},4)=>20}; -assert (t == betti res coker pieri({3,2},{2,2},QQ[a,b,c,d])) -/// - -end -loadPackage "PieriMaps" -installPackage PieriMaps diff --git a/M2/Macaulay2/packages/supplanted-packages/Polyhedra.m2 b/M2/Macaulay2/packages/supplanted-packages/Polyhedra.m2 deleted file mode 100644 index e5ad6ac4ffb..00000000000 --- a/M2/Macaulay2/packages/supplanted-packages/Polyhedra.m2 +++ /dev/null @@ -1,7027 +0,0 @@ ---*- coding: utf-8 -*- ---------------------------------------------------------------------------- --- --- PURPOSE: Computations with convex polyhedra --- PROGRAMMER : René Birkner --- UPDATE HISTORY : April 2008, December 2008, March 2009, Juli 2009, --- September 2009 ---------------------------------------------------------------------------- -newPackage("Polyhedra", - Headline => "A package for computations with convex polyhedra", - Version => "1.0.6", - Date => "September 29, 2009", - Authors => { - {Name => "René Birkner", - HomePage => "http://page.mi.fu-berlin.de/rbirkner/index.htm", - Email => "rbirkner@mi.fu-berlin.de"}} - ) - -export {PolyhedralObject, Polyhedron, Cone, Fan, convexHull, posHull, intersection, makeFan, addCone, - ambDim, cones, genCones, halfspaces, hyperplanes, linSpace, rays, vertices, - areCompatible, commonFace, contains, isCompact, isComplete, isEmpty, isFace, isPointed, isProjective, - isPure, isSmooth, - faces, fVector, hilbertBasis, incompCones, inInterior, interiorPoint, interiorVector, latticePoints, maxFace, minFace, - minkSummandCone, proximum, skeleton, smallestFace, smoothSubfan, tailCone, triangulate, volume, vertexEdgeMatrix, - vertexFacetMatrix, - affineHull, affineImage, affinePreimage, bipyramid, ccRefinement, coneToPolyhedron, directProduct, - dualCone, imageFan, minkowskiSum, normalFan, polar, pyramid, sublatticeBasis, toSublattice, - crossPolytope, cyclicPolytope, ehrhart, emptyPolyhedron, hirzebruch, hypercube, newtonPolytope, posOrthant, statePolytope, - stdSimplex, - saveSession} - -needsPackage "FourierMotzkin" - - --- Defining the new type PolyhedralObject -PolyhedralObject = new Type of HashTable -globalAssignment PolyhedralObject - --- Defining the new type Polyhedron -Polyhedron = new Type of PolyhedralObject -Polyhedron.synonym = "convex polyhedron" -globalAssignment Polyhedron - --- Defining the new type Cone -Cone = new Type of PolyhedralObject -Cone.synonym = "convex rational cone" -globalAssignment Cone - --- Defining the new type Fan -Fan = new Type of PolyhedralObject -globalAssignment Fan - - --- Modifying the standard output for a polyhedron to give an overview of its characteristica -net Polyhedron := P -> ( horizontalJoin flatten ( - "{", - -- prints the parts vertically - stack (horizontalJoin \ sort apply({"ambient dimension", - "dimension of polyhedron", - "dimension of lineality space", - "number of rays", - "number of vertices", - "number of facets"}, key -> (net key, " => ", net P#key))), - "}" )) - - --- Modifying the standard output for a Cone to give an overview of its characteristica -net Cone := C -> ( horizontalJoin flatten ( - "{", - -- prints the parts vertically - stack (horizontalJoin \ sort apply({"ambient dimension", - "dimension of the cone", - "dimension of lineality space", - "number of rays", - "number of facets"}, key -> (net key, " => ", net C#key))), - "}" )) - - --- Modifying the standard output for a Cone to give an overview of its characteristica -net Fan := F -> ( horizontalJoin flatten ( - "{", - -- prints the parts vertically - stack (horizontalJoin \ sort apply({"ambient dimension", - "top dimension of the cones", - "number of generating cones", - "number of rays"}, key -> (net key, " => ", net F#key))), - "}" )) - - - - --- PURPOSE : Computing the Convex Hull of a given set of points and rays -convexHull = method(TypicalValue => Polyhedron) - --- INPUT : 'Mvert' a Matrix containing the generating points as column vectors --- 'Mrays' a Matrix containing the generating rays as column vectors --- OUTPUT : 'P' a Polyhedron --- COMMENT : The description by vertices and rays is stored in P as well as the --- description by defining half-spaces and hyperplanes. -convexHull(Matrix,Matrix) := (Mvert,Mrays) -> ( - -- checking for input errors - if numgens target Mvert =!= numgens target Mrays then error ("points and rays must lie in the same space"); - Mvert = chkZZQQ(Mvert,"points"); - Mrays = chkZZQQ(Mrays,"rays"); - if numRows Mvert == 0 then Mvert = matrix{{0}}; - if numColumns Mvert == 0 then Mvert = map(target Mvert,QQ^1,0); - if numRows Mrays == 0 then Mrays = matrix{{0}}; - if numColumns Mrays == 0 then Mrays = map(target Mrays,QQ^1,0); - -- homogenization of M - Mvert = map(QQ^1,source Mvert,(i,j)->1) || Mvert; - Mrays = map(QQ^1,source Mrays,0) || Mrays; - M := Mvert | Mrays; - -- Computing generators of the cone M and its dual cone - hyperA := fourierMotzkin M; - verticesA := fourierMotzkin hyperA; - polyhedronBuilder(hyperA,verticesA)) - - --- INPUT : 'M' a Matrix containing the generating points as column vectors -convexHull Matrix := M -> ( - -- Checking for input errors - M = chkZZQQ(M,"points"); - if numRows M == 0 then M = matrix{{0}}; - if numColumns M == 0 then M = map(target M,QQ^1,0); - -- Generating the zero ray R - R := map(target M,QQ^1,0); - convexHull(M,R)) - - --- INPUT : '(P1,P2)' two polyhedra -convexHull(Polyhedron,Polyhedron) := (P1,P2) -> ( - -- Checking for input errors - if P1#"ambient dimension" =!= P2#"ambient dimension" then error("Polyhedra must lie in the same ambient space"); - -- Combining the vertices/rays and the lineality spaces in one matrix each - M := (P1#"homogenizedVertices")#0 | (P2#"homogenizedVertices")#0; - LS := (P1#"homogenizedVertices")#1 | (P2#"homogenizedVertices")#1; - hyperA := fourierMotzkin(M,LS); - verticesA := fourierMotzkin hyperA; - polyhedronBuilder(hyperA,verticesA)) - --- INPUT : 'L', a list of Cones, Polyhedra, vertices given by M, --- and (vertices,rays) given by '(V,R)' -convexHull List := L -> ( - -- This function checks if the inserted pair is a pair of matrices that give valid vertices and rays - isValidPair := S -> #S == 2 and if S#1 == 0 then instance(S#0,Matrix) else instance(S#1,Matrix) and numRows S#0 == numRows S#1; - -- Checking for input errors - if L == {} then error("List of convex objects must not be empty"); - P := L#0; - -- The first entry in the list determines the ambient dimension 'n' - n := 0; - local V; - local R; - if (not instance(P,Cone)) and (not instance(P,Polyhedron)) and (not instance(P,Sequence)) and (not instance(P,Matrix)) then - error ("The input must be cones, polyhedra, vertices, or (vertices,rays)."); - -- Adding the vertices and rays to 'V,R', depending on the type of 'P' - if instance(P,Cone) then ( - n = P#"ambient dimension"; - V = map(QQ^n,QQ^1,0); - R = rays P | linSpace P | -(linSpace P)) - else if instance(P,Polyhedron) then ( - n = P#"ambient dimension"; - V = vertices P; - R = rays P | linSpace P | -(linSpace P)) - else if instance(P,Sequence) then ( - -- Checking for input errors - if not isValidPair(P) then error ("Vertices and rays must be given as a sequence of two matrices with the same number of rows"); - V = chkZZQQ(P#0,"vertices"); - n = numRows V; - if P#1 == 0 then R = map(QQ^n,QQ^1,0) - else R = chkZZQQ(P#1,"rays")) - else ( - V = chkZZQQ(P,"vertices"); - n = numRows P; - R = map(QQ^n,QQ^1,0)); - -- Adding the vertices and rays to 'V,R', for each remaining element in 'L', depending on the type of 'P' - L = apply(drop(L,1), C1 -> ( - -- Checking for further input errors - if (not instance(C1,Cone)) and (not instance(C1,Polyhedron)) and (not instance(C1,Sequence)) and - (not instance(C1,Matrix)) then error("The input must be cones, polyhedra, vertices, or (vertices,rays)."); - if instance(C1,Cone) then ( - if ambDim C1 != n then error("All Cones and Polyhedra must be in the same ambient space"); - ({},rays C1 | linSpace C1 | -(linSpace C1))) - else if instance(C1,Polyhedron) then ( - if ambDim C1 != n then error("All Cones and Polyhedra must be in the same ambient space"); - (vertices C1,rays C1 | linSpace C1 | -(linSpace C1))) - else if instance(C1,Sequence) then ( - -- Checking for input errors - if not isValidPair(C1) then error("(Vertices,rays) must be given as a sequence of two matrices with the same number of rows"); - if numRows C1#0 != n then error("(Vertices,rays) must be of the correct dimension."); - if C1#1 != 0 then (chkZZQQ(C1#0,"vertices"),chkZZQQ(C1#1,"rays")) - else (chkZZQQ(C1#0,"vertices"),{})) - else ( - -- Checking for input errors - if numRows C1 != n then error("Vertices must be of the correct dimension."); - (chkZZQQ(C1,"vertices"),{})))); - LV := flatten apply(L, l -> l#0); - if LV != {} then V = V | matrix {LV}; - L = flatten apply(L, l -> l#1); - if L != {} then R = R | matrix {L}; - if R == 0 then convexHull V else convexHull(V,R)) - - - --- PURPOSE : Computing the positive hull of a given set of rays lineality --- space generators -posHull = method(TypicalValue => Cone) - --- INPUT : 'Mrays' a Matrix containing the generating rays as column vectors --- 'LS' a Matrix containing the generating rays of the --- lineality space as column vectors --- OUTPUT : 'C' a Cone --- COMMENT : The description by rays and lineality space is stored in C as well --- as the description by defining half-spaces and hyperplanes. -posHull(Matrix,Matrix) := (Mrays,LS) -> ( - -- checking for input errors - if numRows Mrays =!= numRows LS then error("rays and linSpace generators must lie in the same space"); - Mrays = chkZZQQ(Mrays,"rays"); - LS = chkZZQQ(LS,"lineality space"); - -- Computing generators of the cone and its dual cone - dualgens := fourierMotzkin(Mrays,LS); - genrays := fourierMotzkin dualgens; - coneBuilder(genrays,dualgens)) - - --- INPUT : 'R' a Matrix containing the generating rays as column vectors -posHull Matrix := R -> ( - R = chkZZQQ(R,"rays"); - -- Generating the zero lineality space LS - LS := map(target R,QQ^1,0); - posHull(R,LS)) - - --- INPUT : '(C1,C2)' two cones -posHull(Cone,Cone) := (C1,C2) -> ( - -- Checking for input errors - if C1#"ambient dimension" =!= C2#"ambient dimension" then error("Cones must lie in the same ambient space"); - -- Combining the rays and the lineality spaces into one matrix each - R := C1#"rays" | C2#"rays"; - LS := C1#"linealitySpace" | C2#"linealitySpace"; - dualgens := fourierMotzkin(R,LS); - genrays := fourierMotzkin dualgens; - coneBuilder(genrays,dualgens)) - - --- INPUT : 'P' a Polyhedron -posHull Polyhedron := P -> ( - Mrays := P#"vertices" | P#"rays"; - Mlinspace := P#"linealitySpace"; - posHull(Mrays,Mlinspace)) - - --- INPUT : 'L', a list of Cones, Polyhedra, rays given by R, --- and (rays,linSpace) given by '(R,LS)' -posHull List := L -> ( - -- This function checks if the inserted pair is a pair of matrices that gives valid rays and linSpace - isValidPair := S -> #S == 2 and if S#1 == 0 then instance(S#0,Matrix) else instance(S#1,Matrix) and numRows S#0 == numRows S#1; - -- Checking for input errors - if L == {} then error("List of convex objects must not be empty"); - C := L#0; - -- The first entry in the list determines the ambient dimension 'n' - n := 0; - local R; - local LS; - if (not instance(C,Cone)) and (not instance(C,Polyhedron)) and (not instance(C,Sequence)) and (not instance(C,Matrix)) then - error ("The input must be cones, polyhedra, rays, or (rays,linSpace)."); - -- Adding the vertices and rays to 'R,LS', depending on the type of 'C' - if instance(C,Cone) then ( - n = C#"ambient dimension"; - R = rays C; - LS = linSpace C) - else if instance(C,Polyhedron) then ( - n = C#"ambient dimension"; - R = vertices C | rays C; - LS = linSpace C) - else if instance(C,Sequence) then ( - -- Checking for input errors - if not isValidPair C then error("Rays and lineality space must be given as a sequence of two matrices with the same number of rows"); - R = chkZZQQ(C#0,"rays"); - n = numRows R; - LS = if C#1 == 0 then map(QQ^n,QQ^1,0) else chkZZQQ(C#1,"lineality space")) - else ( - R = chkZZQQ(C,"rays"); - n = numRows R; - LS = map(QQ^n,QQ^1,0)); - -- Adding the rays and lineality spaces to 'R,LS' for each remaining element in 'L', depending on the type of 'C' - L = apply(drop(L,1), C1 -> ( - -- Checking for further input errors - if (not instance(C1,Cone)) and (not instance(C1,Polyhedron)) and (not instance(C1,Sequence)) and - (not instance(C1,Matrix)) then - error ("The input must be cones, polyhedra, rays, or (rays,lineality space)"); - if instance(C1,Cone) then ( - if ambDim C1 != n then error("All Cones and Polyhedra must be in the same ambient space"); - (rays C1,linSpace C1)) - else if instance(C1,Polyhedron) then ( - if ambDim C1 != n then error("All Cones and Polyhedra must be in the same ambient space"); - (vertices C1 | rays C1,linSpace C1)) - else if instance(C1,Sequence) then ( - -- Checking for input errors - if not isValidPair C1 then error("(Rays,lineality space) must be given as a sequence of two matrices with the same number of rows"); - if numRows C1#0 != n then error("(Rays,lineality space) must be of the correct dimension."); - if C1#1 != 0 then (chkZZQQ(C1#0,"rays"),chkZZQQ(C1#1,"lineality space")) - else (chkZZQQ(C1#0,"rays"),{})) - else ( - -- Checking for input errors - if numRows C1 != n then error("Rays must be of the correct dimension."); - (chkZZQQ(C1,"rays"),{})))); - LR := flatten apply(L, l -> l#0); - if LR != {} then R = R | matrix {LR}; - L = flatten apply(L, l -> l#1); - if L != {} then LS = LS | matrix {L}; - if LS == 0 then posHull R else posHull(R,LS)) - - --- PURPOSE : Computing a polyhedron as the intersection of affine half-spaces and hyperplanes -intersection = method() - --- INPUT : '(M,v,N,w)', where all four are matrices (although v and w are only vectors), such --- that the polyhedron is given by P={x | Mx<=v and Nx=w} --- OUTPUT : 'P', the polyhedron -intersection(Matrix,Matrix,Matrix,Matrix) := (M,v,N,w) -> ( - -- checking for input errors - if numColumns M =!= numColumns N then error("equations of half-spaces and hyperplanes must have the same dimension"); - if numRows M =!= numRows v or numColumns v =!= 1 then error("invalid condition vector for half-spaces"); - if numRows N =!= numRows w or numColumns w =!= 1 then error("invalid condition vector for hyperplanes"); - M = -chkZZQQ(v,"condition vector for half-spaces") | chkZZQQ(M,"half-spaces"); - N = -chkZZQQ(w,"condition vector for hyperplanes") | chkZZQQ(N,"hyperplanes"); - -- Computing generators of the cone and its dual cone - M = transpose M | map(source M,QQ^1,(i,j) -> if i == 0 then -1 else 0); - N = transpose N; - verticesA := fourierMotzkin(M,N); - hyperA := fourierMotzkin verticesA; - polyhedronBuilder(hyperA,verticesA)) - - --- INPUT : '(M,N)', two matrices where either 'P' is the Cone {x | Mx<=0, Nx=0} if 'M' and 'N' have the same source space --- or, if 'N' is only a Column vector the Polyhedron {x | Mx<=v} --- OUTPUT : 'P', the Cone or Polyhedron -intersection(Matrix,Matrix) := (M,N) -> ( - -- Checking for input errors - if ((numColumns M =!= numColumns N and numColumns N =!= 1) or (numColumns N == 1 and numRows M =!= numRows N)) and N != 0*N then - error("invalid condition vector for half-spaces"); - local genrays; - local dualgens; - M = chkZZQQ(M,"half-spaces"); - N = chkZZQQ(N,"condition vector for half-spaces"); - -- Decide whether 'M,N' gives the Cone C={p | M*p >= 0, N*p = 0} - if numColumns M == numColumns N and numColumns N != 1 then ( - genrays = fourierMotzkin(-transpose M,transpose N); - dualgens = fourierMotzkin genrays; - coneBuilder(genrays, dualgens)) - -- or the Cone C={p | M*p >= N=0} - else if N == 0*N then ( - genrays = fourierMotzkin (-transpose M); - dualgens = fourierMotzkin genrays; - coneBuilder(genrays,dualgens)) - -- or the Polyhedron P={p | M*p >= N != 0} - else ( -- Computing generators of the Polyhedron and its dual cone - M = -N | M; - M = transpose M | map(source M,QQ^1,(i,j) -> if i == 0 then -1 else 0); - verticesA := fourierMotzkin M; - hyperA := fourierMotzkin verticesA; - polyhedronBuilder(hyperA,verticesA))) - - - - --- INPUT : '(P1,P2)', two polyhedra --- OUTPUT : 'P', the polyhedron that is the intersection of both -intersection(Polyhedron,Polyhedron) := (P1,P2) -> ( - -- Checking if P1 and P2 lie in the same space - if P1#"ambient dimension" =!= P2#"ambient dimension" then error("Polyhedra must lie in the same ambient space"); - -- Combining the Half-spaces and the Hyperplanes - M := (halfspaces P1)#0 || (halfspaces P2)#0; - v := (halfspaces P1)#1 || (halfspaces P2)#1; - N := (hyperplanes P1)#0 || (hyperplanes P2)#0; - w := (hyperplanes P1)#1 || (hyperplanes P2)#1; - intersection(M,v,N,w)) - - --- INPUT : 'M', a matrix, such that the Cone is given by C={x | Mx>=0} --- OUTPUT : 'C', the Cone -intersection Matrix := M -> ( - -- Checking for input errors - M = chkZZQQ(M,"half-spaces"); - -- Computing generators of the cone and its dual cone - genrays := fourierMotzkin (-transpose M); - dualgens := fourierMotzkin genrays; - coneBuilder(genrays,dualgens)) - - - --- INPUT : '(C1,C2)', two Cones --- OUTPUT : 'C', the Cone that is the intersection of both -intersection(Cone,Cone) := (C1,C2) -> ( - -- Checking if C1 and C2 lie in the same space - if C1#"ambient dimension" =!= C2#"ambient dimension" then error("Cones must lie in the same ambient space"); - M := halfspaces C1 || halfspaces C2; - N := hyperplanes C1 || hyperplanes C2; - intersection(M,N)) - - - --- INPUT : '(C,P)', a Cone and a Polyhedron --- OUTPUT : 'Q', the Polyhedron that is the intersection of both -intersection(Cone,Polyhedron) := (C,P) -> intersection {C,P} - - - --- INPUT : '(P,C)', a Polyhedron and a Cone --- OUTPUT : 'Q', the Polyhedron that is the intersection of both -intersection(Polyhedron,Cone) := (P,C) -> intersection {P,C} - - - --- INPUT : 'L', a list of Cones, Polyhedra, inequalities given by (M,v), --- and hyperplanes given by '{N,w}' -intersection List := L -> ( - -- This function checks if the inserted pair is a pair of matrices that gives valid in/equalities - isValidPair := S -> #S == 2 and if S#1 == 0 then instance(S#0,Matrix) else instance(S#1,Matrix) and numRows S#0 == numRows S#1 and numColumns S#1 == 1; - -- Checking for input errors - if L == {} then error("List of cones must not be empty"); - C := L#0; - -- The first entry in the list determines the ambient dimension 'n' - n := 0; - local Ml; - local vl; - local Nl; - local wl; - if (not instance(C,Cone)) and (not instance(C,Polyhedron)) and (not instance(C,Sequence)) and (not instance(C,List)) then - error ("The input must be cones, polyhedra, inequalities, equalities."); - -- Adding the inequalities and equalities to 'M,v,N,w', depending on the type of 'C' - if instance(C,Cone) then ( - n = C#"ambient dimension"; - Ml = -(halfspaces C); - vl = map(target halfspaces C,QQ^1,0); - Nl = hyperplanes C; - wl = map(target hyperplanes C,QQ^1,0)) - else if instance(C,Polyhedron) then ( - n = C#"ambient dimension"; - Ml = (halfspaces C)#0; - vl = (halfspaces C)#1; - Nl = (hyperplanes C)#0; - wl = (hyperplanes C)#1) - else if instance(C,Sequence) then ( - -- Checking for input errors - if not isValidPair C then error("Inequalities must be given as a sequence of a matrix and a column vector"); - Ml = chkZZQQ(C#0,"half-spaces"); - n = numColumns Ml; - vl = if C#1 == 0 then map(target C#0,QQ^1,0) else chkZZQQ(C#1,"condition vector for half-spaces"); - Nl = map(QQ^1,source(C#0),0); - wl = map(QQ^1,QQ^1,0)) - else ( - -- Checking for input errors - if not isValidPair C then error("Equalities must be given as a list of a matrix and a column vector"); - Nl = chkZZQQ(C#0,"hyperplanes"); - n = numColumns Nl; - Ml = map(QQ^1,source C#0,0); - vl = map(QQ^1,QQ^1,0); - wl = if C#1 == 0 then map(target C#0,QQ^1,0) else chkZZQQ(C#1,"condition vector for half-spaces")); - -- Adding the inequalities and equalities to 'M,v,N,w', for each remaining element in 'L', depending on the type of 'C' - L = apply(drop(L,1), C1 -> ( - -- Checking for further input errors - if (not instance(C1,Cone)) and (not instance(C1,Polyhedron)) and (not instance(C1,Sequence)) and (not instance(C1,List)) then - error("The input must be cones, polyhedra, inequalities, equalities."); - if instance(C1,Cone) then ( - if ambDim C1 != n then error("All Cones and Polyhedra must be in the same ambient space"); - (-(halfspaces C1),map(target halfspaces C1,QQ^1,0),hyperplanes C1,map(target hyperplanes C1,QQ^1,0))) - else if instance(C1,Polyhedron) then ( - if ambDim C1 != n then error("All Cones and Polyhedra must be in the same ambient space"); - ((halfspaces C1)#0,(halfspaces C1)#1,(hyperplanes C1)#0,(hyperplanes C1)#1)) - else if instance(C1,Sequence) then ( - -- Checking for input errors - if not isValidPair C1 then error("Inequalities must be given as a sequence of a matrix and a column vector"); - if numColumns C1#0 != n then error("Inequalities must be for the same ambient space."); - C1 = (chkZZQQ(C1#0,"half-spaces"),chkZZQQ(C1#1,"condition vector for half-spaces")); - if C1#1 == 0 then (C1#0,map(target C1#0,QQ^1,0),map(QQ^1,source C1#0,0),map(QQ^1,QQ^1,0)) - else (C1#0,C1#1,map(QQ^1,source C1#0,0),map(QQ^1,QQ^1,0))) - else ( - -- Checking for input errors - if not isValidPair C1 then error("Equalities must be given as a list of a matrix and a column vector"); - if numColumns C1#0 != n then error ("Inequalities must be for the same ambient space."); - C1 = (chkZZQQ(C1#0,"hyperplanes"),chkZZQQ(C1#1,"condition vector for hyperplanes")); - if C1#1 == 0 then (map(QQ^1,source C1#0,0),map(QQ^1,QQ^1,0),C1#0,map(target C1#0,QQ^1,0)) - else (map(QQ^1,source C1#0,0),map(QQ^1,QQ^1,0),C1#0,C1#1)))); - LM := flatten apply(L, l -> entries(l#0)); - if LM != {} then Ml = Ml || matrix LM; - LM = flatten apply(L, l -> entries(l#1)); - if LM != {} then vl = vl || matrix LM; - LM = flatten apply(L, l -> entries(l#2)); - if LM != {} then Nl = Nl || matrix LM; - LM = flatten apply(L, l -> entries(l#3)); - if LM != {} then wl = wl || matrix LM; - if vl == 0*vl and wl == 0*wl then intersection(-Ml,Nl) else intersection(Ml,vl,Nl,wl)); - - - --- PURPOSE : Building the Fan 'F' --- INPUT : 'L', a list of cones and fans in the same ambient space --- OUTPUT : The fan of all Cones in 'L' and all Cones in of the fans in 'L' and all their faces -makeFan = method(TypicalValue => Fan) -makeFan List := L -> ( - -- Checking for input errors - if L == {} then error("List of cones and fans must not be empty"); - if (not instance(L#0,Cone)) and (not instance(L#0,Fan)) then error("Input must be a list of cones and fans"); - -- Starting with the first Cone in the list and extracting its information - C := L#0; - L = drop(L,1); - ad := C#"ambient dimension"; - local F; - if instance(C,Fan) then F = C - else ( - rayList := rays C; - -- Collecting the rays - rayList = apply(numColumns rayList, i-> rayList_{i}); - Ffaces := {}; - completeness := false; - if ad == dim C then ( - Ffaces = faces(1,C); - completeness = Ffaces == {}); - -- Generating the new fan - F = new Fan from { - "generatingCones" => set {C}, - "ambient dimension" => ad, - "top dimension of the cones" => C#"dimension of the cone", - "number of generating cones" => 1, - "rays" => set rayList, - "number of rays" => #rayList, - "isPure" => true, - "faces" => set Ffaces, - "isComplete" => completeness}); - -- Checking the remaining list for input errors and reducing fans in the list - -- to their list of generating cones - L = flatten apply(L, C -> if instance(C,Cone) then C else if instance(C,Fan) then toList(C#"generatingCones") else - error ("Input must be a list of cones and fans")); - -- Adding the remaining cones of the list with 'addCone' - scan(L, C -> F = addCone(C,F)); - F); - - --- INPUT : 'C', a Cone --- OUTPUT : The Fan given by 'C' and all of its faces -makeFan Cone := C -> makeFan {C}; - - - --- PURPOSE : Adding a Cone to an existing fan --- INPUT : '(C,F)', where 'C' is a Cone in the same ambient space as 'F' --- OUTPUT : The original fan 'F' together with 'C' if it is compatible with the already existing cones, --- if not there is an error -addCone = method(TypicalValue => Fan) -addCone (Cone,Fan) := (C,F) -> ( - -- Checking for input errors - if C#"ambient dimension" != F#"ambient dimension" then error("Cones must lie in the same ambient space"); - --Extracting data - GC := toList F#"generatingCones"; - d := C#"dimension of the cone"; - -- We need to memorize for later if 'C' has been inserted - inserted := false; - -- Cones in the list 'GC' are ordered by decreasing dimension so we start compatibility checks with - -- the cones of higher or equal dimension. For this we divide GC into two separate lists - GC = partition(Cf -> (dim Cf) >= d,GC); - GC = {if GC#?true then GC#true else {},if GC#?false then GC#false else {}}; - if all(GC#0, Cf -> ( - (a,b) := areCompatible(Cf,C); - -- if 'Cf' and 'C' are not compatible then there is an error - if not a then error("The cones are not compatible"); - -- if they are compatible and 'C' is a face of 'Cf' then 'C' does not - -- need to be added to 'F' - b != C)) then ( - -- otherwise 'Cf' is still a generating Cone and has to be kept and the remaining cones - -- have to be checked - GC = GC#0 | {C} | select(GC#1, Cf -> ( - (a,b) := areCompatible(Cf,C); - if not a then error("The cones are not compatible"); - -- if one of the remaining cones is a face of 'C' this Cone can be dropped - b != Cf)); - inserted = true) - -- Otherwise 'C' was already a face of one of the original cones and does not need to be added - else GC = flatten GC; - -- If 'C' was added to the Fan as a generating cone then the codim 1 faces on the boundary have to changed to check for - -- completeness - Ffaces := toList F#"faces"; - completeness := F#"isComplete"; - rayList := toList F#"rays"; - if inserted then ( - if d == C#"ambient dimension" then ( - facets := faces(1,C); - (sFfaces,sfacets) := (set Ffaces,set facets); - Ffaces = join(select(Ffaces,i->not sfacets#?i),select(facets,i->not sFfaces#?i)); - completeness = Ffaces == {}); - -- The rays of 'C' have to be added - rm := rays C; - rm = apply(numColumns rm, i -> rm_{i}); - rayList = unique(rayList|rm)); - -- Saving the fan - new Fan from { - "generatingCones" => set GC, - "ambient dimension" => F#"ambient dimension", - "top dimension of the cones" => dim GC#0, - "number of generating cones" => #GC, - "rays" => set rayList, - "number of rays" => #rayList, - "isPure" => true, - "faces" => set Ffaces, - "isComplete" => completeness}) - - --- INPUT : '(L,F)', where 'L' is a list of Cones in the same ambient space as the fan 'F' --- OUTPUT : The original fan 'F' together with cones in the list 'L' -addCone (List,Fan) := (L,F) -> ( - -- Checking for input errors - if L == {} then error("The list must not be empty"); - if (not instance(L#0,Cone)) and (not instance(L#0,Fan)) then error("The list may only contain cones and fans"); - if #L == 1 then addCone(L#0,F) else addCone(drop(L,1),addCone(L#0,F))) - - --- INPUT : '(F1,F)', where 'F1' is a fan in the same ambient space as the fan 'F' --- OUTPUT : The original fan 'F' together with cones of the fan 'F1' -addCone (Fan,Fan) := (F1,F) -> ( - -- Checking for input errors - if ambDim F != ambDim F1 then error("The fans must be in the same ambient space"); - L := toList F1#"generatingCones"; - addCone(L,F)) - - --- PURPOSE : Giving the defining affine hyperplanes -ambDim = method(TypicalValue => ZZ) - --- INPUT : 'P' a Polyhedron --- OUTPUT : an integer, the dimension of the ambient space -ambDim Polyhedron := P -> P#"ambient dimension" - --- INPUT : 'C' a Cone --- OUTPUT : an integer, the dimension of the ambient space -ambDim Cone := C -> C#"ambient dimension" - --- INPUT : 'F' a Fan --- OUTPUT : an integer, the dimension of the ambient space -ambDim Fan := F -> F#"ambient dimension" - - - --- PURPOSE : Giving the k dimensional Cones of the Fan --- INPUT : (k,F) where 'k' is a positive integer and F is a Fan --- OUTPUT : a List of Cones -cones = method(TypicalValue => List) -cones(ZZ,Fan) := (k,F) -> ( - -- Checking for input errors - if k < 0 or dim F < k then error("k must be between 0 and the dimension of the fan."); - L := select(toList F#"generatingCones", C -> dim C >= k); - -- Collecting the 'k'-dim faces of all generating cones of dimension greater than 'k' - unique flatten apply(L, C -> faces(dim(C)-k,C))) - - - --- INPUT : 'P' a Polyhedron --- OUTPUT : an integer, the dimension of the polyhedron -dim Polyhedron := P -> P#"dimension of polyhedron" - - --- INPUT : 'C' a Cone --- OUTPUT : an integer, the dimension of the Cone -dim Cone := C -> C#"dimension of the cone" - - --- INPUT : 'F' a Fan --- OUTPUT : an integer, the highest dimension of Cones in 'F' -dim Fan := F -> F#"top dimension of the cones" - - --- PURPOSE : Giving the generating Cones of the Fan --- INPUT : 'F' a Fan --- OUTPUT : a List of Cones -genCones = method(TypicalValue => List) -genCones Fan := F -> toList F#"generatingCones" - - - --- PURPOSE : Giving the defining affine half-spaces --- INPUT : 'P' a Polyhedron --- OUTPUT : '(M,v)', where M and v are matrices and P={x in H | Mx<=v}, where --- H is the intersection of the defining affine hyperplanes -halfspaces = method() -halfspaces Polyhedron := P -> P#"halfspaces" - - --- INPUT : 'C' a Cone --- OUTPUT : 'M', where M is a matrix and C={x in H | Mx>=0}, where --- H is the intersection of the defining hyperplanes -halfspaces Cone := C -> C#"halfspaces" - - - --- PURPOSE : Giving the defining affine hyperplanes --- INPUT : 'P' a Polyhedron --- OUTPUT : '(N,w)', where M and v are matrices and P={x in HS | Nx=w}, where --- HS is the intersection of the defining affine half-spaces -hyperplanes = method() -hyperplanes Polyhedron := P -> P#"hyperplanes" - - --- INPUT : 'C' a Cone -hyperplanes Cone := C -> C#"hyperplanes" - - - --- PURPOSE : Giving a basis of the lineality space -linSpace = method(TypicalValue => Matrix) - --- INPUT : 'P' a Polyhedron --- OUTPUT : a Matrix, where the column vectors are a basis of the lineality space -linSpace Polyhedron := P -> P#"linealitySpace" - - --- INPUT : 'C' a Cone --- OUTPUT : a Matrix, where the column vectors are a basis of the lineality space -linSpace Cone := C -> C#"linealitySpace" - - --- INPUT : 'F' a Fan --- OUTPUT : a Matrix, where the column vectors are a basis of the lineality space -linSpace Fan := F -> ((toList F#"generatingCones")#0)#"linealitySpace" - - --- PURPOSE : Giving the rays --- INPUT : 'P' a Polyhedron --- OUTPUT : a Matrix, containing the rays of P as column vectors -rays = method(TypicalValue => Matrix) -rays Polyhedron := P -> P#"rays" - - --- INPUT : 'C' a Cone -rays Cone := C -> C#"rays" - - --- INPUT : 'F' a Fan -rays Fan := F -> toList F#"rays" - - - --- PURPOSE : Giving the vertices --- INPUT : 'P' a Polyhedron --- OUTPUT : a Matrix, containing the vertices of P as column vectors -vertices = method(TypicalValue => Matrix) -vertices Polyhedron := P -> P#"vertices" - - - --- PURPOSE : Tests whether the intersection of two Cones is a face of both --- INPUT : '(C1,C2)' two Cones --- OUTPUT : '(Boolean,Cone)' (true,the intersection),if their intersection is a face of each and --- (false,the intersection) otherwise. If the two cones do not lie in --- the same ambient space it returns the empty polyhedron instead of --- the intersection -areCompatible = method() -areCompatible(Cone,Cone) := (C1,C2) -> ( - if C1#"ambient dimension" == C2#"ambient dimension" then ( - I := intersection(C1,C2); - (isFace(I,C1) and isFace(I,C2),I)) - else (false,emptyPolyhedron(C1#"ambient dimension"))) - - --- PURPOSE : Tests whether the intersection of two Polyhedra/Cones is a face of both -commonFace = method(TypicalValue => Boolean) - --- INPUT : '(P,Q)' two Polyhedra --- OUTPUT : 'true' or 'false' -commonFace(Polyhedron,Polyhedron) := (P,Q) -> ( - if P#"ambient dimension" == Q#"ambient dimension" then ( - I := intersection(P,Q); - isFace(I,P) and isFace(I,Q)) - else false) - --- INPUT : '(C1,C2)' two Cones --- OUTPUT : 'true' or 'false' -commonFace(Cone,Cone) := (C1,C2) -> ( - if C1#"ambient dimension" == C2#"ambient dimension" then ( - I := intersection(C1,C2); - isFace(I,C1) and isFace(I,C2)) - else false) - - --- INPUT : '(C,F)' a Cone and a Fan --- OUTPUT : 'true' or 'false' --- COMMENT : For this it checks if the cone has a common face with every generating cone of the fan -commonFace(Cone,Fan) := (C,F) -> if C#"ambient dimension" == F#"ambient dimension" then all(genCones F, C1 -> commonFace(C,C1)) else false - - --- INPUT : '(F,C)' a Fan and a Cone --- OUTPUT : 'true' or 'false' --- COMMENT : For this it checks if the cone has a common face with every generating cone of the fan -commonFace(Fan,Cone) := (F,C) -> commonFace(C,F) - - --- INPUT : '(F1,F2)' two Fans --- OUTPUT : 'true' or 'false' --- COMMENT : For this it checks if all generating cones of 'F1' have a common face with every generating cone of 'F2' -commonFace(Fan,Fan) := (F1,F2) -> all(genCones F1, C -> commonFace(C,F2)) - - - --- PURPOSE : Check if 'P' contains 'Q' --- INPUT : '(P,Q)' two Polyhedra --- OUTPUT : 'true' or 'false' -contains = method(TypicalValue => Boolean) -contains(Polyhedron,Polyhedron) := (P,Q) -> ( - -- checking for input errors - if P#"ambient dimension" =!= Q#"ambient dimension" then error("Polyhedra must lie in the same ambient space"); - -- Saving the equations of P and vertices/rays of Q - (A,B) := P#"homogenizedHalfspaces"; - (C,D) := Q#"homogenizedVertices"; - A = transpose A; - B = transpose B; - E := A*C; - -- Checking if vertices/rays of Q satisfy the equations of P - all(flatten entries E, e -> e <= 0) and A*D == 0*A*D and B*C == 0*B*C and B*D == 0*B*D) - - --- PURPOSE : Check if 'C1' contains 'C2' --- INPUT : '(C1,C2)' two Cones -contains(Cone,Cone) := (C1,C2) -> ( - -- checking for input errors - if C1#"ambient dimension" =!= C2#"ambient dimension" then error("Cones must lie in the same ambient space"); - -- Saving the equations of C1 and rays of C2 - (A,B) := C1#"dualgens"; - (C,D) := C2#"genrays"; - A = transpose A; - B = transpose B; - E := A*C; - -- Checking if the rays of C2 satisfy the equations of C1 - all(flatten entries E, e -> e <= 0) and A*D == 0*A*D and B*C == 0*B*C and B*D == 0*B*D) - - - --- PURPOSE : Check if 'C' contains 'P' --- INPUT : '(C,P)' a Cone and a Polyhedron -contains(Cone,Polyhedron) := (C,P) -> ( - -- checking for input errors - if C#"ambient dimension" =!= P#"ambient dimension" then error("Cone and Polyhedron must lie in the same ambient space"); - -- Saving the equations of C and vertices/rays of P - M := P#"vertices" | P#"rays"; - LS := P#"linealitySpace"; - C1 := posHull(M,LS); - contains(C,C1)) - - - --- PURPOSE : Check if 'P' contains 'C' --- INPUT : '(P,C)' a Polyhedron and a Cone -contains(Polyhedron,Cone) := (P,C) -> ( - -- checking for input errors - if C#"ambient dimension" =!= P#"ambient dimension" then error("Polyhedron and Cone must lie in the same ambient space"); - -- Saving the cone 'C' as a polyhedron and using the function on two polyhedra - Q := coneToPolyhedron C; - contains(P,Q)) - - - --- PURPOSE : Check if 'P' contains 'p' --- INPUT : '(P,p)' a Polyhedron 'P' and a point 'p' given as a matrix -contains(Polyhedron,Matrix) := (P,p) -> ( - -- checking for input errors - if P#"ambient dimension" =!= numRows p then error("Polyhedron and point must lie in the same ambient space"); - if numColumns p =!= 1 then error("The point must be given as a one row matrix"); - contains(P,convexHull p)) - - - --- PURPOSE : Check if 'C' contains 'p' --- INPUT : '(C,p)' a Cone 'C' and a point 'p' given as a matrix -contains(Cone,Matrix) := (C,p) -> ( - -- checking for input errors - if C#"ambient dimension" =!= numRows p then error("Polyhedron and point must lie in the same ambient space"); - if numColumns p =!= 1 then error("The point must be given as a one row matrix"); - contains(C,convexHull p)) - - - --- PURPOSE : Check if a list of cones 'L' contains 'C' --- INPUT : '(L,C)' a List of cones 'L' and a Cone 'C' -contains(List,Cone) := (L,C) -> any(L, C1 -> C1 == C) - - --- PURPOSE : Check if a list of cones 'L' contains 'C' --- INPUT : '(L,C)' a List of cones 'L' and a Cone 'C' -contains(List,Polyhedron) := (L,P) -> any(L, Q -> Q == P) - - --- PURPOSE : Check if 'F' contains 'C' --- INPUT : '(F,C)' a Fan 'F' and a Cone 'C' -contains(Fan,Cone) := (F,C) -> ( - -- Checking for input errors - if ambDim F != ambDim C then error("Fan and Cone must lie in the same ambient space"); - -- Making the list of cones of same dimension as 'C' - L := cones(dim C,F); - contains(L,C)) - - - -Polyhedron == Polyhedron := (P,Q) -> P === Q - -Cone == Cone := (C1,C2) -> C1 === C2 - -Fan == Fan := (F1,F2) -> F1 === F2 - - - - --- PURPOSE : Tests if a Polyhedron is compact --- INPUT : 'P' a Polyhedron --- OUTPUT : 'true' or 'false' -isCompact = method(TypicalValue => Boolean) -isCompact Polyhedron := P -> P#"linealitySpace" == 0 and P#"rays" == 0 - - --- PURPOSE : Tests if a Fan is complete --- INPUT : 'F' a Fan --- OUTPUT : 'true' or 'false' -isComplete = method(TypicalValue => Boolean) -isComplete Fan := F -> F#"isComplete" - - --- PURPOSE : Tests if a Polyhedron is empty --- INPUT : 'P' a Polyhedron --- OUTPUT : 'true' or 'false' -isEmpty = method(TypicalValue => Boolean) -isEmpty Polyhedron := P -> P#"dimension of polyhedron" == -1 - - - --- PURPOSE : Tests if the first Polyhedron/Cone is a face of the second Polyhedron/Cone -isFace = method(TypicalValue => Boolean) - --- INPUT : '(P,Q)' two Polyhedra --- OUTPUT : 'true' or 'false' -isFace(Polyhedron,Polyhedron) := (P,Q) -> ( - -- Checking if the two polyhedra lie in the same space and computing the dimension difference - c := Q#"dimension of polyhedron" - P#"dimension of polyhedron"; - if P#"ambient dimension" == Q#"ambient dimension" and c >= 0 then ( - -- Checking if P is the empty polyhedron - if c > Q#"dimension of polyhedron" then true - -- Checking if one of the codim 'c' faces of Q is P - else any(faces(c,Q), f -> f === P)) - else false) - --- INPUT : '(C1,C2)' two Cones --- OUTPUT : 'true' or 'false' -isFace(Cone,Cone) := (C1,C2) -> ( - c := C2#"dimension of the cone" - C1#"dimension of the cone"; - -- Checking if the two cones lie in the same space and the dimension difference is positive - if C1#"ambient dimension" == C2#"ambient dimension" and c >= 0 then ( - -- Checking if one of the codim 'c' faces of C2 is C1 - any(faces(c,C2), f -> f === C1)) - else false) - -isNormal Polyhedron := P -> ( - -- Checking for input errors - if not isCompact P then error ("The polyhedron must be compact"); - -- Computing the Hilbert basis of the cone over 'P' on height 1 - V := vertices P || map(QQ^1,source vertices P,(i,j) -> 1); - L := hilbertBasis posHull V; - n := ambDim P; - -- Do all lattice points lie in height one? - all(L,v -> v_(n,0) == 1)) - - --- PURPOSE : Tests if a Cone is pointed --- INPUT : 'C' a Cone --- OUTPUT : 'true' or 'false' -isPointed = method(TypicalValue => Boolean) -isPointed Cone := C -> rank C#"linealitySpace" == 0 - - --- INPUT : 'F', a Fan --- OUTPUT : 'true' or 'false' -isPointed Fan := F -> isPointed((toList F#"generatingCones")#0) - - - --- PURPOSE : Tests if a Fan is projective --- INPUT : 'F' a Fan --- OUTPUT : a Polyhedron, which has 'F' as normal fan, if 'F' is projective or the empty polyhedron -isProjective = method(TypicalValue => Polyhedron) -isProjective Fan := F -> ( - resultingPolytope := emptyPolyhedron ambDim F; - -- First of all the fan must be complete - if isComplete F then ( - -- Extracting the generating cones, the ambient dimension, the codim 1 - -- cones (corresponding to the edges of the polytope if it exists) - i := 0; - L := hashTable apply(toList F#"generatingCones", l -> (i=i+1; i=>l)); - n := F#"ambient dimension"; - edges := cones(n-1,F); - -- Making a table that indicates in which generating cones each 'edge' is contained - edgeTCTable := hashTable apply(edges, e -> select(1..#L, j -> contains(L#j,e)) => e); - i = 0; - -- Making a table of all the edges where each entry consists of the pair of top cones corr. to - -- this edge, the codim 1 cone, an index number i, and the edge direction from the first to the - -- second top Cone - edgeTable := apply(pairs edgeTCTable, e -> (i=i+1; - v := transpose hyperplanes e#1; - if not contains(dualCone L#((e#0)#0),v) then v = -v; - (e#0, e#1, i, v))); - edgeTCNoTable := hashTable apply(edgeTable, e -> e#0 => (e#2,e#3)); - edgeTable = hashTable apply(edgeTable, e -> e#1 => (e#2,e#3)); - -- Computing the list of correspondencies, i.e. for each codim 2 cone ( corresponding to 2dim-faces of the polytope) save - -- the indices of the top cones containing it - corrList := hashTable {}; - scan(keys L, j -> (corrList = merge(corrList,hashTable apply(faces(2,L#j), C -> C => {j}),join))); - corrList = pairs corrList; - -- Generating the 0 matrix for collecting the conditions on the edges - m := #(keys edgeTable); - NM := map(QQ^n,QQ^m,0); - -- for each entry of corrlist another matrix is added to HP - HP := flatten apply(#corrList, j -> ( - v := corrList#j#1; - HPnew := NM; - -- Scanning through the top cones containing the active codim2 cone and order them in a circle by their - -- connecting edges - v = apply(v, e -> L#e); - C := v#0; - v = drop(v,1); - C1 := C; - nv := #v; - scan(nv, i -> ( - i = position(v, e -> dim intersection(C1,e) == n-1); - C2 := v#i; - v = drop(v,{i,i}); - (a,b) := edgeTable#(intersection(C1,C2)); - if not contains(dualCone C2,b) then b = -b; - -- 'b' is the edge direction inserted in column 'a', the index of this edge - HPnew = HPnew_{0..a-2} | b | HPnew_{a..m-1}; - C1 = C2)); - C3 := intersection(C,C1); - (a,b) := edgeTable#C3; - if not contains(dualCone C,b) then b = -b; - -- 'b' is the edge direction inserted in column 'a', the index of this edge - -- the new restriction is that the edges ''around'' this codim2 Cone must add up to 0 - entries(HPnew_{0..a-2} | b | HPnew_{a..m-1}))); - if HP != {} then HP = matrix HP - else HP = map(QQ^0,QQ^m,0); - -- Find an interior vector in the cone of all positive vectors satisfying the restrictions - v := flatten entries interiorVector intersection(id_(QQ^m),HP); - M := {}; - -- If the vector is strictly positive then there is a polytope with 'F' as normalFan - if all(v, e -> e > 0) then ( - -- Construct the polytope - i = 1; - -- Start with the origin - p := map(QQ^n,QQ^1,0); - M = {p}; - Lyes := {}; - Lno := {}; - vlist := apply(keys edgeTCTable,toList); - -- Walk along all edges recursively - edgerecursion := (i,p,vertexlist,Mvertices) -> ( - vLyes := {}; - vLno := {}; - -- Sorting those edges into 'vLyes' who emerge from vertex 'i' and the rest in 'vLno' - vertexlist = partition(w -> member(i,w),vertexlist); - if vertexlist#?true then vLyes = vertexlist#true; - if vertexlist#?false then vLno = vertexlist#false; - -- Going along the edges in 'vLyes' with the length given in 'v' and calling edgerecursion again with the new index of the new - -- top Cone, the new computed vertex, the remaining edges in 'vLno' and the extended matrix of vertices - scan(vLyes, w -> ( - w = toSequence w; - j := edgeTCNoTable#w; - if w#0 == i then ( - (vLno,Mvertices) = edgerecursion(w#1,p+(j#1)*(v#((j#0)-1)),vLno,append(Mvertices,p+(j#1)*(v#((j#0)-1))))) - else ( - (vLno,Mvertices) = edgerecursion(w#0,p-(j#1)*(v#((j#0)-1)),vLno,append(Mvertices,p-(j#1)*(v#((j#0)-1))))))); - (vLno,Mvertices)); - -- Start the recursion with vertex '1', the origin, all edges and the vertexmatrix containing already the origin - M = unique ((edgerecursion(i,p,vlist,M))#1); - M = matrix transpose apply(M, m -> flatten entries m); - -- Computing the convex hull - resultingPolyhedron = convexHull M)); - resultingPolyhedron) - - - --- PURPOSE : Checks if the Fan is of pure dimension --- INPUT : 'F' a Fan --- OUTPUT : 'true' or 'false' -isPure = method(TypicalValue => Boolean) -isPure Fan := F -> F#"isPure" - - --- PURPOSE : Checks if the input is smooth -isSmooth = method(TypicalValue => Boolean) - --- INPUT : 'C' a Cone --- OUTPUT : 'true' or 'false' -isSmooth Cone := C -> ( - -- generating the non-linealityspace cone of C - smooth := false; - R := rays C; - C = posHull R; - -- if the cone is full dimensional then it is smooth iff its rays form a basis over ZZ - if dim C == ambDim C then numColumns R == numRows R and abs det R == 1 - -- otherwise the rays must be part of a basis over ZZ - else ( - if numColumns R == dim C then ( - A := (smithNormalForm R)#0; - det(A^{0..(numColumns A)-1}) == 1) - else false)) - - --- INPUT : 'F' a Fan --- OUTPUT : 'true' or 'false' -isSmooth Fan := F -> all(toList F#"generatingCones",isSmooth) - - - --- PURPOSE : Computing the faces of codimension 'k' of 'P' --- INPUT : 'k' an integer between 0 and the dimension of --- 'P' a polyhedron --- OUTPUT : a List, containing the faces as polyhedra -faces = method(TypicalValue => List) -faces(ZZ,Polyhedron) := (k,P) -> ( - --Checking for input errors - if k < 0 or k > dim P then error("the codimension must be between 0 and the dimension of the polyhedron"); - d := dim P - k; - dl := P#"dimension of lineality space"; - -- Saving the lineality space of 'P', which is the also the lineality space of each face - LS := P#"linealitySpace"; - -- for d = dim P it is the polyhedron itself - if d == dim P then {P} - -- for k=dim(P) the faces are the vertices - else if d == dl then ( - V := vertices P; - -- Generating the list of vertices with each vertex as a polyhedron - apply(numColumns V, i -> convexHull(V_{i},LS))) - else if d < dl then {} - else ( - -- Saving the half-spaces and hyperplanes - (HS,v) := halfspaces P; - (HP,w) := hyperplanes P; - -- Generating the list of facets where each facet is given by a list of its vertices and a list of its rays - F := apply(numRows HS, i -> intersection(HS,v,HP || HS^{i},w || v^{i})); - F = apply(F, f -> ( - V := vertices f; - R := rays f; - (set apply(numColumns V, i -> V_{i}),set apply(numColumns R, i -> R_{i})))); - -- Duplicating the list of facets - L := F; - i := 1; - -- Intersecting L k-1 times with F and returning the maximal inclusion sets which are the faces of codim plus 1 - while i < k do ( - L = intersectionWithFacets(L,F); - i = i+1); - -- Generating the corresponding polytopes out of the lists of vertices, rays and the lineality space - L = apply(L, l -> ( - l = (toList l#0,toList l#1); - V := matrix transpose apply(l#0, e -> flatten entries e); - R := if l#1 != {} then matrix transpose apply(l#1, e -> flatten entries e) else map(target V,QQ^1,0); - if LS != 0 then R = R | LS | -LS; - convexHull(V,R))); - L)) - - - --- INPUT : 'k' an integer between 0 and the dimension of --- 'C' a polyhedron --- OUTPUT : a List, containing the faces as cones -faces(ZZ,Cone) := (k,C) -> ( - d := dim C - k; - dl := C#"dimension of lineality space"; - LS := linSpace C; - --Checking for input errors - if d < 0 or d > dim C then error("the codimension must be between 0 and the dimension of the cone") - -- for d = dim C it is the cone itself - else if d == dim C then {C} - -- for d = dl it is the lineality space - else if d == dl then {posHull(LS | -LS)} - -- for d = dl+1 it is the lineality space plus one of the rays - else if d == dl+1 then ( - -- Generating the list of cones given by one ray and the lineality space - R := rays C; - apply(numColumns R, i -> posHull(R_{i},LS))) - else if 0 <= d and d < dl then {} - else ( - -- Saving the half-spaces and hyperplanes - HS := halfspaces C; - HP := hyperplanes C; - -- Generating the list of facets where each facet is given by a list of its vertices and a list of its rays - F := apply(numRows HS, i -> intersection(HS,HP || HS^{i})); - F = apply(F, f -> ( - R := rays f; - (set apply(numColumns R, i -> R_{i})))); - -- Duplicating the list of facets - L := F; - i := 1; - -- Intersecting L k-1 times with F and returning the maximal inclusion sets. These are the faces of codim plus 1 - while i < k do ( - L = intersectionWithFacetsCone(L,F); - i = i+1); - -- Generating the corresponding polytopes out of the lists of vertices, rays and the lineality space - apply(L, l -> posHull(matrix transpose apply(toList l, e -> flatten entries e),LS)))) - - --- PURPOSE : Computing the f-vector of a polyhedron --- INPUT : 'P' a Polyhedron --- OUTPUT : a List of integers, starting with the number of vertices and going up in dimension -fVector = method(TypicalValue => List) -fVector Polyhedron := P -> apply(P#"dimension of polyhedron" + 1, d -> #faces(dim P - d,P)) - - --- INPUT : 'C' a Cone --- OUTPUT : a List of integers, starting with the number of vertices and going up in dimension -fVector Cone := C -> apply(C#"dimension of the cone" + 1, d -> #faces(dim C - d,C)) - - --- PURPOSE : Computing the Hilbert basis of a Cone --- INPUT : 'C', a Cone --- OUTPUT : 'L', a list containing the Hilbert basis as one column matrices -hilbertBasis = method(TypicalValue => List) -hilbertBasis Cone := C -> ( - -- Computing the row echolon form of the matrix M - ref := M -> ( - n := numColumns M; - s := numRows M; - BC := map(ZZ^n,ZZ^n,1); - m := min(n,s); - -- Scan through the first square part of 'M' - i := 0; - stopper := 0; - while i < m and stopper < n do ( - -- Selecting the first non-zero entry after the i-th row in the i-th column - j := select(1,toList(i..s-1),k -> M_i_k != 0); - -- if there is a non-zero entry, scan the remaining entries and compute the reduced form for this column - if j != {} then ( - j = j#0; - scan((j+1)..(s-1), k -> ( - if M_i_k != 0 then ( - a := M_i_j; - b := M_i_k; - L := gcdCoefficients(a,b); - a = substitute(a/(L#0),ZZ); - b = substitute(b/(L#0),ZZ); - M = M^{0..j-1} || (L#1)*M^{j} + (L#2)*M^{k} || M^{j+1..k-1} || (-b)*M^{j} + a*M^{k} || M^{k+1..s-1}))); - if i != j then ( - M = M^{0..i-1} || M^{j} || M^{i+1..j-1} || M^{i} || M^{j+1..s-1}); - if M_i_i < 0 then M = M^{0..i-1} || -M^{i} || M^{i+1..s-1}) - else ( - M = M_{0..i-1} | M_{i+1..n-1} | M_{i}; - BC = BC_{0..i-1} | BC_{i+1..n-1} | BC_{i}; - i = i-1); - i = i+1; - stopper = stopper + 1); - (M,BC)); - -- Function to compute the/one preimage of h under A - preim := (h,A) -> ( - -- Take the generators of the kernel of '-h|A' and find an element with 1 as first entry -> the other entries are a preimage - -- vector - N := gens ker(-h|A); - N = transpose (ref transpose N)#0; - N_{0}^{1..(numRows N)-1}); - A := C#"halfspaces"; - if C#"hyperplanes" != 0 then A = A || C#"hyperplanes" || -(C#"hyperplanes"); - A = substitute(A,ZZ); - -- Use the project and lift algorithm to compute a basis of the space of vectors positive on 'A' whose preimages are the HilbertBasis - (B,BC) := ref transpose A; - H := constructHilbertBasis B; - BC = inverse transpose BC; - apply(H,h -> preim(BC*h,A))) - - --- PURPOSE : Get the pairs of incompatible cones in a list of cones --- INPUT : 'L', a list of cones and fans --- OUTPUT : 'Lpairs', a list, empty if there is no pair of incompatible cones, otherwise it contains the pairs of cones/fans that are --- not compatible -incompCones = method(TypicalValue => List) -incompCones List := L -> ( - if any(L, l -> (not instance(l,Cone)) and (not instance(l,Fan))) then error("The list may only contain cones and fans"); - select(apply(subsets(L,2),toSequence), p -> not commonFace p)) - - --- INPUT : '(C,F)', a cone and a fan --- OUTPUT : 'Lpairs', a list, empty if there is no pair of incompatible cones, otherwise it contains the pairs of 'C' with the cones of --- 'F' that are not compatible -incompCones(Cone,Fan) := (C,F) -> select(apply(genCones F, f -> (C,f)), p -> not commonFace p) - - --- INPUT : '(F,C)', a fan and a cone --- OUTPUT : 'Lpairs', a list, empty if there is no pair of incompatible cones, otherwise it contains the pairs of 'C' with the cones of --- 'F' that are not compatible -incompCones(Fan,Cone) := (F,C) -> select(apply(genCones F, f -> (f,C)), p -> not commonFace p) - - --- INPUT : '(F1,F2)', two fans --- OUTPUT : 'Lpairs', a list, empty if there is no pair of incompatible cones, otherwise it contains the pairs of cones of 'F1' and cones of --- 'F2' that are not compatible -incompCones(Fan,Fan) := (F1,F2) -> flatten apply(genCones F1, C1 -> flatten apply(genCones F2, C2 -> if not commonFace(C1,C2) then (C1,C2) else {})) - - - --- PURPOSE : Checking if a point is an interior point of a Polyhedron or Cone -inInterior = method(TypicalValue => Boolean) - - --- INPUT : '(p,P)', where 'p' is a point given by a matrix and 'P' is a Polyhedron --- OUTPUT : 'true' or 'false' -inInterior (Matrix,Polyhedron) := (p,P) -> smallestFace(p,P) === P - - --- INPUT : '(p,C)', where 'p' is a point given by a matrix and 'C' is a Cone --- OUTPUT : 'true' or 'false' -inInterior (Matrix,Cone) := (p,C) -> smallestFace(p,C) === C - - --- PURPOSE : Computing a point in the relative interior of a cone or Polyhedron -interiorPoint = method(TypicalValue => Matrix) - - --- INPUT : 'P', a Polyhedron --- OUTPUT : 'p', a point given as a matrix -interiorPoint Polyhedron := P -> ( - -- Checking for input errors - if isEmpty P then error("The polyhedron must not be empty"); - Vm := vertices P; - n := numColumns Vm; - ones := matrix toList(n:{1/n}); - -- Take the '1/n' weighted sum of the vertices - Vm * ones) - - --- PURPOSE : Computing an interior vector of a cone --- INPUT : 'C', a Cone --- OUTPUT : 'p', a point given as a matrix -interiorVector = method(TypicalValue => Matrix) -interiorVector Cone := C -> ( - if dim C == 0 then map(QQ^(ambDim C),QQ^1,0) - else ( - Rm := rays C; - ones := matrix toList(numColumns Rm:{1_QQ}); - -- Take the sum of the rays - iv := Rm * ones; - d := abs gcd flatten entries iv; - (1/d)*iv)) - - --- PURPOSE : Computing the lattice points of a compact Polyhedron --- INPUT : 'P', a Polyhedron --- OUTPUT : 'L', a list containing the lattice points of 'P' -latticePoints = method(TypicalValue => List) -latticePoints Polyhedron := P -> ( - -- Checking for input errors - if not isCompact P then error("The polyhedron must be compact"); - -- Recursive function that intersects the polyhedron with parallel hyperplanes in the axis direction - -- in which P has its minimum extension - latticePointsRec := P -> ( - -- Finding the direction with minimum extension of P - V := entries vertices P; - n := ambDim P; - minv := apply(V,min); - maxv := apply(V,max); - minmaxv := maxv-minv; - pos := min minmaxv; - pos = position(minmaxv,v -> v == pos); - -- Determining the lattice heights in this direction - L := toList({{ceiling minv_pos}}..{{floor maxv_pos}}); - -- If the dimension is one, than it is just a line and we take the lattice points - if n == 1 then apply(L,matrix) - -- Otherwise intersect with the hyperplanes and project into the hyperplane - else flatten apply(L,p -> ( - NP := intersection {P,{map(QQ^1,QQ^n,(i,j) -> if j == pos then 1 else 0),matrix p}}; - if NP#"number of vertices" == 1 then ( - v := vertices NP; - if promote(substitute(v,ZZ),QQ) == v then substitute(v,ZZ) else {}) - else ( - A := matrix drop((entries id_(QQ^n)),{pos,pos}); - apply(latticePointsRec affineImage(A,NP),v -> v^{0..(pos-1)} || matrix p || v^{pos..(n-2)}))))); - -- Checking if the polytope is full dimensional - if (dim P == ambDim P) then latticePointsRec P - -- If not checking first if the affine hull of P contains lattice points at all and if so projecting the polytope down - -- so that it becomes full dimensional with a map that keeps the lattice - else ( - (M,v) := hyperplanes P; - -- Finding a lattice point in the affine hull of P - b := if all(entries M, e -> gcd e == 1) then ( - -- Computing the Smith Normal Form to solve the equation over ZZ - (M1,Lmatrix,Rmatrix) := smithNormalForm substitute(M,ZZ); - v1 := flatten entries (Lmatrix*v); - w := apply(numRows M1, i -> M1_(i,i)); - -- Checking if the system is at least solvable over QQ - if all(#w, i -> w#i != 0 or v1#i == 0) then ( - -- If it is, then solve over QQ - w = apply(#w, i -> (v1#i/w#i,v1#i%w#i)); - if all(w, e -> e#1 == 0) then ( - -- If the solution is in fact in ZZ then return it - w = transpose matrix{apply(w,first) | toList(numColumns M1 - numRows M1:0)}; - Rmatrix * w))); - -- If there is no lattice point in the affine hull then P has none - if b === null then {} - else ( - A := gens ker substitute(M,ZZ); - -- Project the translated polytope, compute the lattice points and map them back - apply(latticePoints affinePreimage(A,P,b),e -> substitute(A*e + b,ZZ))))) - - - --- PURPOSE : Computing the face of a Polyhedron where a given weight attains its maximum --- INPUT : '(v,P)', a weight vector 'v' given by a one column matrix over ZZ or QQ and a --- Polyhedron 'P' --- OUTPUT : a Polyhedron, the face of 'P' where 'v' attains its maximum -maxFace = method() -maxFace (Matrix,Polyhedron) := (v,P) -> minFace(-v,P) - - --- INPUT : '(v,P)', a weight vector 'v' given by a one column matrix over ZZ or QQ and a --- Cone 'C' --- OUTPUT : a Cone, the face of 'P' where 'v' attains its maximum -maxFace (Matrix,Cone) := (v,C) -> minFace(-v,C) - - - --- PURPOSE : Computing the face of a Polyhedron where a given weight attains its minimum --- INPUT : '(v,P)', a weight vector 'v' given by a one column matrix over ZZ or QQ and a --- Polyhedron 'P' --- OUTPUT : a Polyhedron, the face of 'P' where 'v' attains its minimum -minFace = method() -minFace (Matrix,Polyhedron) := (v,P) -> ( - -- Checking for input errors - if numColumns v =!= 1 or numRows v =!= P#"ambient dimension" then error("The vector must lie in the same space as the polyhedron"); - C := dualCone tailCone P; - V := vertices P; - R := rays P; - LS := linSpace P; - -- The weight must lie in the dual of the tailcone of the polyhedron, otherwise there is - -- no minimum and the result is the empty polyhedron - if contains(C,v) then ( - -- Compute the values of 'v' on the vertices of 'V' - Vind := flatten entries ((transpose v)*V); - -- Take the minimal value(s) - Vmin := min Vind; - Vind = positions(Vind, e -> e == Vmin); - -- If 'v' is in the interior of the dual tailCone then the face is exactly spanned - -- by these vertices - if inInterior(v,C) then convexHull(V_Vind,LS | -LS) - else ( - -- Otherwise, one has to add the rays of the tail cone that are orthogonal to 'v' - Rind := flatten entries ((transpose v)*R); - Rind = positions(Rind, e -> e == 0); - convexHull(V_Vind,R_Rind | LS | -LS))) - else emptyPolyhedron ambDim P) - - - --- PURPOSE : Computing the face of a Cone where a given weight attains its minimum --- INPUT : '(v,P)', a weight vector 'v' given by a one column matrix over ZZ or QQ and a --- Cone 'C' --- OUTPUT : a Cone, the face of 'P' where 'v' attains its minimum -minFace (Matrix,Cone) := (v,C) -> ( - -- Checking for input errors - if numColumns v =!= 1 or numRows v =!= C#"ambient dimension" then error("The vector must lie in the same space as the polyhedron"); - R = rays C; - LS = linSpace C; - C = dualCone C; - -- The weight must lie in the dual of the cone, otherwise there is - -- no minimum and the result is the empty polyhedron - if contains(C,v) then ( - -- Take the rays of the cone that are orthogonal to 'v' - Rind := flatten entries ((transpose v)*R); - Rind = positions(Rind, e -> e == 0); - posHull(R_Rind,LS)) - else emptyPolyhedron ambDim P) - - - --- PURPOSE : Computing the Cone of the Minkowskisummands of a Polyhedron 'P', the minimal --- Minkowskisummands, and minimal decompositions --- INPUT : 'P', a polyhedron --- OUTPUT : '(C,L,M)' where 'C' is the Cone of the Minkowskisummands, 'L' is a list of --- Polyhedra corresponding to the generators of 'C', and 'M' is a --- matrix where the columns give the minimal decompositions of 'P'. -minkSummandCone = method() -minkSummandCone Polyhedron := P -> ( - -- Subfunction to save the two vertices of a compact edge in a matrix where the vertex with the smaller entries comes first - -- by comparing the two vertices entry-wise - normvert := M -> ( - M = toList M; - v := (M#0)-(M#1); - normrec := w -> if (entries w)#0#0 > 0 then 0 else if (entries w)#0#0 < 0 then 1 else (w = w^{1..(numRows w)-1}; normrec w); - i = normrec v; - if i == 1 then M = {M#1,M#0}; - M); - -- If the polyhedron is 0 or 1 dimensional itself is its only summand - if dim P == 0 or dim P == 1 then (posHull matrix{{1}}, hashTable {0 => P},matrix{{1}}) - else ( - -- Extracting the data to compute the 2 dimensional faces and the edges - d := P#"ambient dimension"; - dP := P#"dimension of polyhedron"; - (HS,v) := halfspaces P; - (HP,w) := hyperplanes P; - F := apply(numRows HS, i -> intersection(HS,v,HP || HS^{i},w || v^{i})); - F = apply(F, f -> ( - V := vertices f; - R := rays f; - (set apply(numColumns V, i -> V_{i}),set apply(numColumns R, i -> R_{i})))); - LS := linSpace P; - L := F; - i := 1; - while i < dP-2 do ( - L = intersectionWithFacets(L,F); - i = i+1); - -- Collect the compact edges - L1 = select(L, l -> l#1 === set{}); - -- if the polyhedron is 2 dimensional and not compact then every compact edge with the tailcone is a summand - if dim P == 2 and (not isCompact P) then ( - L1 = intersectionWithFacets(L,F); - L1 = select(L, l -> l#1 === set{}); - if #L1 == 0 or #L1 == 1 then (posHull matrix{{1}},hashTable {0 => P},matrix{{1}}) - else ( - TailC := rays P; - if linSpace P != 0 then TailC = TailC | linSpace P | -linSpace(P); - (posHull map(QQ^(#L1),QQ^(#L1),1),hashTable apply(#L1, i -> i => convexHull((L1#i)#0 | (L1#i)#1,TailC)),matrix toList(#L1:{1_QQ})))) - else ( - -- If the polyhedron is compact and 2 dimensional then there is only one 2 faces - if dim P == 2 then L1 = {(set apply(numColumns vertices P, i -> (vertices P)_{i}), set {})}; - edges := {}; - edgesTable := edges; - condmatrix := map(QQ^0,QQ^0,0); - scan(L1, l -> ( - -- for every 2 face we get a couple of rows in the condition matrix for the edges of this 2 face - -- for this the edges if set in a cyclic order must add up to 0. These conditions are added to - -- 'condmatrix' by using the indices in edges - ledges := apply(intersectionWithFacets({l},F), e -> normvert e#0); - -- adding e to edges if not yet a member - newedges := select(ledges, e -> not member(e,edges)); - -- extending the condmatrix by a column of zeros for the new edge - condmatrix = condmatrix | map(target condmatrix,QQ^(#newedges),0); - edges = edges | newedges; - -- Bring the edges into cyclic order - oedges := {(ledges#0,1)}; - v := ledges#0#1; - ledges = drop(ledges,1); - nledges := #ledges; - oedges = oedges | apply(nledges, i -> ( - i = position(ledges, e -> e#0 == v or e#1 == v); - e := ledges#i; - ledges = drop(ledges,{i,i}); - if e#0 == v then ( - v = e#1; - (e,1)) - else ( - v = e#0; - (e,-1)))); - M := map(QQ^d,source condmatrix,0); - -- for the cyclic order in oedges add the corresponding edgedirections to condmatrix - scan(oedges, e -> ( - ve := (e#0#1 - e#0#0)*(e#1); - j := position(edges, edge -> edge == e#0); - M = M_{0..j-1} | ve | M_{j+1..(numColumns M)-1})); - condmatrix = condmatrix || M)); - -- if there are no conditions then the polyhedron has no compact 2 faces - if condmatrix == map(QQ^0,QQ^0,0) then ( - -- collect the compact edges - LL := select(faces(dim P - 1,P), fLL -> isCompact fLL); - -- if there is only none or one compact edge then the only summand is the polyhedron itself - if #LL == 0 or #LL == 1 then (posHull matrix{{1}}, hashTable {0 => P},matrix{{1}}) - -- otherwise we get a summand for each compact edge - else ( - TailCLL := rays P; - if linSpace P != 0 then TailCLL = TailCLL | linSpace P | -linSpace(P); - (posHull map(QQ^(#LL),QQ^(#LL),1),hashTable apply(#LL, i -> i => convexHull(vertices LL#i,TailCLL)),matrix toList(#LL:{1_QQ})))) - -- Otherwise we can compute the Minkowski summand cone - else ( - Id := map(source condmatrix,source condmatrix,1); - C := intersection(Id,condmatrix); - R := rays C; - TC := map(QQ^(P#"ambient dimension"),QQ^1,0) | P#"rays" | P#"linealitySpace" | -(P#"linealitySpace"); - v = (vertices P)_{0}; - -- computing the actual summands - summList := hashTable apply(numColumns R, i -> ( - remedges := edges; - -- recursive function which takes 'L' the already computed vertices of the summandpolyhedron, - -- the set of remaining edges, the current vertex of the original polyhedron, the current - -- vertex of the summandpolyhedron, and the ray of the minkSummandCone. It computes the - -- edges emanating from the vertex, scales these edges by the corresponding factor in mi, - -- computes the vertices at the end of those edges (for the original and for the - -- summandpolyhedron) and calls itself with each of the new vertices, if there are edges - -- left in the list - edgesearch := (v,v0,mi) -> ( - remedges = partition(e -> member(v,e),remedges); - Lnew := {}; - if remedges#?true then Lnew = apply(remedges#true, e -> ( - j := position(edges, edge -> edge == e); - edir := e#0 + e#1 - 2*v; - vnew := v0 + (mi_(j,0))*edir; - (v+edir,vnew,vnew != v0))); - if remedges#?false then remedges = remedges#false else remedges = {}; - L := apply(select(Lnew, e -> e#2),e -> e#1); - Lnew = apply(Lnew, e -> (e#0,e#1)); - L = L | apply(Lnew, (u,w) -> if remedges =!= {} then edgesearch(u,w,mi) else {}); - flatten L); - mi := R_{i}; - v0 := map(QQ^d,QQ^1,0); - -- Calling the edgesearch function to get the vertices of the summand - L := {v0} | edgesearch(v,v0,mi); - L = matrix transpose apply(L, e -> flatten entries e); - i => convexHull(L,TC))); - -- computing the inclusion minimal decompositions - onevec := matrix toList(numRows R: {1_QQ}); - negId := map(source R,source R,-1); - zerovec := map(source R,QQ^1,0); - Q := intersection(negId,zerovec,R,onevec); - (C,summList,vertices(Q)))))) - - - --- PURPOSE : Computing the closest point of a polyhedron to a given point --- INPUT : (p,P), where 'p' is a point given by a one column matrix over ZZ or QQ and --- 'P' is a Polyhedron --- OUTPUT : the point in 'P' with the minimal euclidean distance to 'p' -proximum = method(TypicalValue => Matrix) -proximum (Matrix,Polyhedron) := (p,P) -> ( - -- Checking for input errors - if numColumns p =!= 1 or numRows p =!= P#"ambient dimension" then error("The point must lie in the same space"); - if isEmpty P then error("The polyhedron must not be empty"); - -- Defining local variables - local Flist; - d := ambDim P; - c := 0; - prox := {}; - -- Checking if 'p' is contained in 'P' - if contains(P,p) then p - else ( - V := vertices P; - R := rays P; - -- Distinguish between full dimensional polyhedra and not full dimensional ones - if dim P == d then ( - -- Continue as long as the proximum has not been found - while instance(prox,List) do ( - -- Take the faces of next lower dimension of P - c = c+1; - if c == dim P then ( - Vdist := apply(numColumns V, j -> ((transpose(V_{j}-p))*(V_{j}-p))_(0,0)); - pos := min Vdist; - pos = position(Vdist, j -> j == pos); - prox = V_{pos}) - else ( - Flist = faces(c,P); - -- Search through the faces - any(Flist, F -> ( - -- Take the inward pointing normal cone with respect to P - (vL,bL) := hyperplanes F; - -- Check for each ray if it is pointing inward - vL = matrix apply(numRows vL, i -> ( - v := vL^{i}; - b := first flatten entries bL^{i}; - if all(flatten entries (v*(V | R)), e -> e >= b) then flatten entries v - else flatten entries(-v))); - -- Take the polyhedron spanned by the inward pointing normal cone - -- and 'p' and intersect it with the face - Q := intersection(F,convexHull(p,transpose vL)); - -- If this intersection is not empty, it contains exactly one point, - -- the proximum - if not isEmpty Q then ( - prox = vertices Q; - true) - else false)))); - prox) - else ( - -- For not full dimensional polyhedra the hyperplanes of 'P' have to be considered also - while instance(prox,List) do ( - if c == dim P then ( - Vdist1 := apply(numColumns V, j -> ((transpose(V_{j}-p))*(V_{j}-p))_(0,0)); - pos1 := min Vdist1; - pos1 = position(Vdist1, j -> j == pos1); - prox = V_{pos1}) - else ( - Flist = faces(c,P); - -- Search through the faces - any(Flist, F -> ( - -- Take the inward pointing normal cone with respect to P - (vL,bL) := hyperplanes F; - vL = matrix apply(numRows vL, i -> ( - v := vL^{i}; - b := first flatten entries bL^{i}; - entryList := flatten entries (v*(V | R)); - -- the first two ifs find the vectors not in the hyperspace - -- of 'P' - if any(entryList, e -> e > b) then flatten entries v - else if any(entryList, e -> e < b) then flatten entries(-v) - -- If it is an original hyperplane than take the direction from - -- 'p' to the polyhedron - else ( - bCheck := first flatten entries (v*p); - if bCheck < b then flatten entries v - else flatten entries(-v)))); - Q = intersection(F,convexHull(p,transpose vL)); - if not isEmpty Q then ( - prox = vertices Q; - true) - else false))); - c = c+1); - prox))) - - --- INPUT : (p,C), where 'p' is a point given by a one column matrix over ZZ or QQ and --- 'C' is a Cone --- OUTPUT : the point in 'C' with the minimal euclidean distance to 'p' -proximum (Matrix,Cone) := (p,C) -> proximum(p,coneToPolyhedron C) - - --- PURPOSE : Computing the 'n'-skeleton of a fan --- INPUT : (n,F), where 'n' is a positive integer and --- 'F' is a Fan --- OUTPUT : the Fan consisting of the 'n' dimensional cones in 'F' -skeleton = method(TypicalValue => Fan) -skeleton(ZZ,Fan) := (n,F) -> ( - -- Checking for input errors - if n < 0 or dim F < n then error("The integer must be between 0 and dim F"); - makeFan(cones(n,F))) - - --- PURPOSE : Computing the smallest face of 'P' containing 'p' --- INPUT : '(p,P)', where 'p' is a point given as a matrix and --- 'P' is a polyhedron --- OUTPUT : The smallest face containing 'p' as a polyhedron -smallestFace = method() -smallestFace(Matrix,Polyhedron) := (p,P) -> ( - -- Checking for input errors - if numColumns p =!= 1 or numRows p =!= P#"ambient dimension" then error("The point must lie in the same space"); - p = chkZZQQ(p,"point"); - -- Checking if 'P' contains 'p' at all - if contains(P,convexHull p) then ( - (M,v) := halfspaces P; - (N,w) := hyperplanes P; - -- Selecting the half-spaces that fulfil equality for p - -- and adding them to the hyperplanes - pos := select(toList(0..(numRows M)-1), i -> (M^{i})*p == v^{i}); - N = N || M^pos; - w = w || v^pos; - intersection(M,v,N,w)) - else emptyPolyhedron P#"ambient dimension") - - - --- INPUT : '(p,C)', where 'p' is point given as a matrix and --- 'C' is a Cone --- OUTPUT : The smallest face containing 'p' as a cone -smallestFace(Matrix,Cone) := (p,C) -> ( - -- Checking for input errors - if numColumns p =!= 1 or numRows p =!= C#"ambient dimension" then error("The point must lie in the same space"); - p = chkZZQQ(p,"point"); - -- Checking if 'C' contains 'p' at all - if contains(C,posHull p) then ( - M := halfspaces C; - N := hyperplanes C; - -- Selecting the half-spaces that fulfil equality for p - -- and adding them to the hyperplanes - pos := select(toList(0..(numRows M)-1), i -> (M^{i})*p == 0); - N = N || M^pos; - intersection(M,N)) - else emptyPolyhedron C#"ambient dimension") - - - --- PURPOSE : Computing the subfan of all smooth cones of the Fan --- INPUT : 'F', a Fan --- OUTPUT : The Fan of smooth cones -smoothSubfan = method(TypicalValue => Fan) -smoothSubfan Fan := F -> ( - -- recursive function that adds the cones of the list 'L' to 'F' if they are smooth - -- and calls itself with the faces of the cone if the cone is not smooth - facerecursion := L -> flatten apply(L, C -> if isSmooth C then C else facerecursion faces(1,C)); - L := toList F#"generatingCones"; - makeFan facerecursion L) - - - --- PURPOSE : Computing the tail cone of a given Polyhedron --- INPUT : 'P', a Polyhedron --- OUTPUT : The Cone generated by the rays and the lineality space of 'P' -tailCone = method(TypicalValue => Cone) -tailCone Polyhedron := P -> posHull(P#"rays",P#"linealitySpace") - - - --- PURPOSE : Triangulating a compact Polyhedron --- INPUT : 'P', a Polyhedron --- OUTPUT : A list of the simplices of the triangulation. Each simplex is given by a list --- of its vertices. ---COMMENTS : The triangulation is build recursively, for each face that is not a simplex it takes --- the weighted centre of the face. for each codim 1 face of this face it either takes the --- convex hull with the centre if it is a simplex or triangulates this in the same way. -triangulate = method() -triangulate Polyhedron := P -> ( - -- Defining the recursive face triangulation - -- This takes a polytope and computes all facets. For each facet that is not a simplex, it calls itself - -- again to replace this facet by a triangulation of it. then it has a list of simplices triangulating - -- the facets. Then it computes for each of these simplices the convex hull with the weighted centre of - -- the input polytope. The weighted centre is the sum of the vertices divided by the number of vertices. - -- It returns the resulting list of simplices in a list, where each simplex is given by a list of its - -- vertices. - -- The function also needs the dimension of the Polyhedron 'd', the list of facets of the original - -- polytope, the list 'L' of triangulations computed so far and the dimension of the original Polytope. - -- 'L' contains a hash table for each dimension of faces of the original Polytope (i.e. from 0 to 'n'). - -- If a face has been triangulated than the list of simplices is saved in the hash table of the - -- corresponding dimension with the weighted centre of the original face as key. - recursiveFaceTriangulation := (P,d,originalFacets,L,n) -> ( - -- Computing the facets of P, given as lists of their vertices - F := intersectionWithFacets({(set P,set{})},originalFacets); - F = apply(F, f -> toList(f#0)); - d = d-1; - -- if the facets are at least 2 dimensional, then check if they are simplices, if not call this - -- function again - if d > 1 then ( - F = flatten apply(F, f -> ( - -- Check if the face is a simplex - if #f != d+1 then ( - -- Computing the weighted centre - p := (sum f)*(1/#f); - -- Taking the hash table of the corresponding dimension - -- Checking if the triangulation has been computed already - if L#d#?p then L#d#p - else ( - -- if not, call this function again for 'f' and then save this in 'L' - (f,L) = recursiveFaceTriangulation(f,d,originalFacets,L,n); - L = merge(L,hashTable {d => hashTable{p => f}},(x,y) -> merge(x,y,)); - f)) - else {f}))); - -- Adding the weighted centre to each face simplex - q := (sum P)*(1/#P); - P = apply(F, f -> f | {q}); - (P,L)); - -- Checking for input errors - if not isCompact P then error("The polytope must be compact!"); - n := dim P; - -- Computing the facets of P as lists of their vertices - (HS,v) := halfspaces P; - (HP,w) := hyperplanes P; - originalFacets := apply(numRows HS, i -> intersection(HS,v, HP || HS^{i}, w || v^{i})); - originalFacets = apply(originalFacets, f -> ( - V := vertices f; - (set apply(numColumns V, i -> V_{i}),set {}))); - -- Making a list of the vertices of P - P = vertices P; - P = apply(numColumns P, i -> P_{i}); - d := n; - -- Initiating the list of already computed triangulations - L := hashTable apply(n+1, i -> i => hashTable {}); - (P,L) = recursiveFaceTriangulation(P,d,originalFacets,L,n); - P) - - - --- PURPOSE : Computing the volume of a full dimensional polytope --- INPUT : 'P', a compact polyhedron --- OUTPUT : QQ, giving the volume of the polytope -volume = method(TypicalValue => QQ) -volume Polyhedron := P -> ( - d := dim P; - -- Checking for input errors - if d != ambDim P then error("The polytope must be full dimensional."); - if not isCompact P then error("The polyhedron must be compact, i.e. a polytope."); - -- Computing the triangulation of P - P = triangulate P; - -- Computing the volume of each simplex without the dimension factor, by - -- taking the absolute of the determinant of |v_1-v_0..v_d-v_0| - P = apply(P, p -> abs det matrix transpose apply(toList(1..d), i -> flatten entries(p#i - p#0))); - -- Summing up the volumes and dividing out the dimension factor - (sum P)/(d!)) - - - - --- PURPOSE : Computing the vertex-edge-matrix of a polyhedron --- INPUT : 'P', a polyhedron --- OUTPUT : a matrix, where the columns are indexed by the edges and the rows indexed by the vertices and has 1 as entry --- if the corresponding edge contains this vertex -vertexEdgeMatrix = method(TypicalValue => Matrix) -vertexEdgeMatrix Polyhedron := P -> ( - -- list the edges and the vertices - eP := apply(faces(dim P -1,P),f -> ( - f = vertices f; - set apply(numColumns f, i -> f_{i}))); - vp := vertices P; - vp = apply(numColumns vp, i -> vp_{i}); - d := #vp; - n := #eP; - -- Generate the matrix with indices in the first row and column and for every edge add two 1's in the corresponding column - transpose matrix {toList(0..d)} | ( matrix {toList(1..n)} || matrix apply(vp,v -> apply(eP,e -> if e#?v then 1 else 0)))) - - - --- PURPOSE : Computing the vertex-facet-matrix of a polyhedron --- INPUT : 'P', a polyhedron --- OUTPUT : a matrix, where the columns are indexed by the facets and the rows are indexed by the vertices and has 1 as entry --- if the corresponding facet contains this vertex -vertexFacetMatrix = method(TypicalValue => Matrix) -vertexFacetMatrix Polyhedron := P -> ( - -- list the facets and the vertices - fP := apply(faces(1,P),f -> ( - f = vertices f; - set apply(numColumns f, i -> f_{i}))); - vp := vertices P; - vp = apply(numColumns vp, i -> vp_{i}); - d := #vp; - n := #fP; - -- Generate the matrix with indices in the first row and column and for every facet add 1's in the corresponding column - transpose matrix {toList(0..d)} | ( matrix {toList(1..n)} || matrix apply(vp, v -> apply(fP,f -> if f#?v then 1 else 0)))) - - - - --- PURPOSE : Computing the affine hull --- INPUT : 'P', a Polyhedron --- OUTPUT : the affine hull of 'P' as a Polyhedron -affineHull = method(TypicalValue => Polyhedron) -affineHull Polyhedron := P -> ( - M := vertices P; - R := rays P; - -- subtracting the first vertex from all other vertices - N := (M+M_{0}*(matrix {toList(numColumns M:-1)}))_{1..(numColumns M)-1}; - convexHull(M_{0},N | -N | R | -R)); - - --- PURPOSE : Computing the affine image of a polyhedron -affineImage = method(TypicalValue => Polyhedron) - --- INPUT : '(A,P,v)', where 'A' is a ZZ or QQ matrix from the ambient space of the --- polyhedron 'P' to some other target space and 'v' is a matrix --- defining a vector in the target space of 'A' --- OUTPUT : a polyhedron, the affine image of 'P': --- A*P+v={A*p+v | p in P} -affineImage(Matrix,Polyhedron,Matrix) := (A,P,v) -> ( - -- Checking for input errors - A = chkZZQQ(A,"linear map"); - v = chkZZQQ(v,"translation vector"); - if P#"ambient dimension" =!= numColumns A then error("Matrix source must be ambient space"); - if numRows A =!= numRows v then error("Vector must lie in target space of matrix"); - if numColumns v =!= 1 then error("Second argument must be a vector"); - -- Generating nr of vertices many copies of v - v = v * (matrix {toList(P#"number of vertices":1_QQ)}); - Mv := A*(vertices P) + v; - Mr := A*(rays P); - if numColumns Mr == 0 then Mr = matrix toList(numRows Mv:{0_QQ}); - convexHull(Mv,Mr)) - - --- INPUT : '(A,P)', where 'A' is a ZZ or QQ matrix from the ambient space of the --- polyhedron 'P' to some other target space --- OUTPUT : A Polyhedron, the image of 'P' under 'A' -affineImage(Matrix,Polyhedron) := (A,P) -> ( - -- Generating the zero translation vector - A = chkZZQQ(A,"map"); - v := map(target A,QQ^1,0); - affineImage(A,P,v)) - - --- INPUT : '(P,v)', where 'v' is a ZZ or QQ one-column matrix describing a point in --- the ambient space of the polyhedron 'P' --- OUTPUT : A Polyhedron, the translation of 'P' by 'v', i.e. {p+v | p in P} -affineImage(Polyhedron,Matrix) := (P,v) -> ( - -- Generating the identity matrix - A := map(QQ^(P#"ambient dimension"),QQ^(P#"ambient dimension"),1); - affineImage(A,P,v)) - - --- INPUT : '(M,C,v)', where 'M' is a ZZ or QQ matrix from the ambient space of --- the cone 'C' to some target space and 'v' is a matrix --- defining a vector in that target space --- OUTPUT : A polyhedron, the affine image of 'C': --- (M*C)+v={(M*c)+v | c in C} -affineImage(Matrix,Cone,Matrix) := (M,C,v) -> if v == 0 then affineImage(M,C) else affineImage(M,coneToPolyhedron C,v) - - --- INPUT : '(M,C)', where 'M' is a ZZ or QQ matrix from the --- ambient space of the cone 'C' to some target space --- OUTPUT : A cone, the affine image of 'C': --- M*C={M*c | c in C} -affineImage(Matrix,Cone) := (M,C) -> posHull affineImage(M,coneToPolyhedron C) - - --- INPUT : '(C,v)', where 'C' is a cone and 'v' is a matrix --- defining a vector in the ambient space of 'C' --- OUTPUT : A polyhedron, the affine image of 'C': --- C+v={c+v | c in C} -affineImage(Cone,Matrix) := (C,v) -> affineImage(coneToPolyhedron C,v) - - --- PURPOSE : Computing the affine preimage of a cone or polyhedron -affinePreimage = method(TypicalValue => Polyhedron) - --- INPUT : '(A,P,b)', where 'A' is a ZZ or QQ matrix from some source space to the --- ambient space of the polyhedron 'P' and 'b' is a matrix --- defining a vector in the ambient space of 'P' --- OUTPUT : A polyhedron, the affine preimage of 'P': --- {q | (A*q)+b in P} -affinePreimage(Matrix,Polyhedron,Matrix) := (A,P,b) -> ( - -- Checking for input errors - A = chkZZQQ(A,"linear map"); - b = chkZZQQ(b,"translation vector"); - if P#"ambient dimension" =!= numRows A then error("Matrix source must be ambient space"); - if numRows A =!= numRows b then error("Vector must lie in target space of matrix"); - if numColumns b =!= 1 then error("Second argument must be a vector"); - -- Constructing the new half-spaces and hyperplanes - (M,v) := halfspaces P; - (N,w) := hyperplanes P; - v = v - (M * b); - w = w - (N * b); - M = M * A; - N = N * A; - intersection(M,v,N,w)) - - --- INPUT : '(A,P)', where 'A' is a ZZ or QQ matrix from some source space to the --- ambient space of the polyhedron 'P' -affinePreimage(Matrix,Polyhedron) := (A,P) -> ( - -- Generating the zero translation vector - A = chkZZQQ(A,"map"); - affinePreimage(A,P,map(target A,QQ^1,0))) - - --- INPUT : '(P,b)', where 'b' is a ZZ or QQ one-column matrix describing a point in --- the ambient space of the polyhedron 'P' --- OUTPUT : A Polyhedron, the negative translation of 'P' by 'b', i.e. {q | q+b in P} -affinePreimage(Polyhedron,Matrix) := (P,b) -> affinePreimage(map(QQ^(P#"ambient dimension"),QQ^(P#"ambient dimension"),1),P,b) - - --- INPUT : '(A,C,b)', where 'A' is a ZZ or QQ matrix from some source space to the --- ambient space of the cone 'C' and 'b' is a matrix --- defining a vector in the ambient space of 'C' --- OUTPUT : A polyhedron, the affine preimage of 'C': --- {q | (A*q)+b in C} --- or a cone, the affine preimage of 'C' if 'b' is 0: --- {q | (A*q) in C} -affinePreimage(Matrix,Cone,Matrix) := (A,C,b) -> if b == 0 then affinePreimage(A,C) else affinePreimage(A,coneToPolyhedron C,b) - - --- INPUT : '(A,C)', where 'A' is a ZZ or QQ matrix from some source space to the --- ambient space of the cone 'C' --- OUTPUT : A cone, the affine preimage of 'C': --- {q | (A*q) in C} -affinePreimage(Matrix,Cone) := (A,C) -> posHull affinePreimage(A,coneToPolyhedron C) - - --- INPUT : '(C,b)', where 'b' is a ZZ or QQ one-column matrix describing a point in --- the ambient space of the cone 'C' --- OUTPUT : A polyhedron, the affine preimage of 'C': --- {q | q+b in C} -affinePreimage(Cone,Matrix) := (C,b) -> affinePreimage(coneToPolyhedron C,b) - - --- PURPOSE : Computing the bipyramid over the polyhedron 'P' --- INPUT : 'P', a polyhedron --- OUTPUT : A polyhedron, the convex hull of 'P', embedded into ambientdim+1 space and the --- points (barycenter of 'P',+-1) -bipyramid = method(TypicalValue => Polyhedron) -bipyramid Polyhedron := P -> ( - -- Saving the vertices - V := vertices P; - n := numColumns V; - if n == 0 then error("P must not be empty"); - -- Computing the barycenter of P - v := matrix toList(n:{1_QQ,1_QQ}); - v = (1/n)*V*v; - (M,LS) := P#"homogenizedVertices"; - -- Embedding into n+1 space and adding the two new vertices - zerorow := map(QQ^1,source M,0); - newvertices := matrix {{1_QQ,1_QQ}} || v || matrix {{1_QQ,-(1_QQ)}}; - M = (M || zerorow) | newvertices; - LS = LS || map(QQ^1,source LS,0); - hyperA := fourierMotzkin(M,LS); - verticesA := fourierMotzkin hyperA; - polyhedronBuilder(hyperA,verticesA)) - - --- PURPOSE : Computes the coarsest common refinement of a given set of rays --- INPUT : 'M' a Matrix --- OUTPUT : 'F' a Fan, the coarsest common refinement of the rays in 'M' -ccRefinement = method(TypicalValue => Fan) -ccRefinement Matrix := M -> ( - -- Checking for input errors - M = chkZZQQ(M,"rays"); - -- Extracting data - n := numRows M; - m := numColumns M; - -- Generating all cones generated by 'n' rays in 'M' - nCones := apply(subsets(m,n), e -> posHull M_e); - -- Selecting those cones that are 'n' dimensional and do not contain any - -- of the others - nConesfd := select(nCones, C -> dim C == n); - nConesfd = inclMinCones nConesfd; - refCones := {}; - while nConesfd != {} do ( - newCones := {}; - -- scan through the 'n' dimensional cones and check for each of the cones generated by - -- 'n' rays if their intersection is 'n' dimensional and if the first one is not contained - -- in the latter. If true, then their intersection will be saved in the list 'newCones'. - -- If false for every cone generated by 'n' rays, then the 'n' dimensional cone will be - -- appended to the list 'refCones' - refCones = refCones | (flatten apply(nConesfd, C1 -> ( - toBeAdded := flatten apply(nCones, C2 -> ( - C := intersection(C2,C1); - if dim C == n and (not contains(C2,C1)) then C - else {})); - if toBeAdded == {} then C1 - else ( - newCones = newCones | toBeAdded; - {})))); - -- now, the new intersections will be the 'n' dimensional cones and the same procedure - -- starts over again if this list is not empty - nConesfd = unique newCones); - -- Compute the fan generated by the 'refCones' - makeFan refCones); - - --- PURPOSE : Converts the Cone 'C' into itself as a Polyhedron 'P' --- INPUT : 'C' a Cone --- OUTPUT : 'P' the Cone saved as a polyhedron -coneToPolyhedron = method(TypicalValue => Polyhedron) -coneToPolyhedron Cone := C -> ( - M := map(QQ^(C#"ambient dimension"),QQ^1,0); - N := rays C; - convexHull(M,N)) - - --- PURPOSE : Computing the direct product of two polyhedra in the direct product of their ambient spaces -directProduct = method() - --- INPUT : '(P,Q)', two polyhedra --- OUTPUT : A polyhedron, the direct product -directProduct (Polyhedron,Polyhedron) := (P,Q) -> ( - -- Extracting half-spaces and hyperplanes of P and Q - (Mp,vp) := halfspaces P; - (Np,wp) := hyperplanes P; - (Mq,vq) := halfspaces Q; - (Nq,wq) := hyperplanes Q; - -- Constructing the new half-spaces matrix |Mp 0 | and vector |vp| - -- |0 Mq| |vq| - M := Mp ++ Mq; - v := vp || vq; - -- Constructing the new hyperplanes matrix |Np 0 | and vector |wp| - -- |0 Nq| |wq| - N := Np ++ Nq; - w := wp || wq; - intersection(M,v,N,w)) - - --- INPUT : '(C1,C2)', two cones --- OUTPUT : A cone, the direct product -directProduct (Cone,Cone) := (C1,C2) -> ( - -- Extracting half-spaces and hyperplanes of P and Q - Mp := halfspaces C1; - Np := hyperplanes C1; - Mq := halfspaces C2; - Nq := hyperplanes C2; - -- Constructing the new half-spaces matrix |Mp 0 | - -- |0 Mq| - M := Mp ++Mq; - -- Constructing the new hyperplanes matrix |Np 0 | - -- |0 Nq| - N := Np ++ Nq; - intersection(M,N)) - - --- INPUT : '(C,P)', a cone and a polyhedron --- OUTPUT : A polyhedron, the direct product -directProduct (Cone,Polyhedron) := (C,P) -> directProduct(coneToPolyhedron C,P) - - --- INPUT : '(P,C)', a polyhedron and a cone --- OUTPUT : A polyhedron, the direct product -directProduct (Polyhedron,Cone) := (P,C) -> directProduct(P,coneToPolyhedron C) - - --- INPUT : '(F1,F2)', two fans --- OUTPUT : A fan, the direct product -directProduct (Fan,Fan) := (F1,F2) -> ( - -- computing the direct products of all pairs of generating cones - makeFan flatten apply(toList F1#"generatingCones", C1 -> apply(toList F2#"generatingCones", C2 -> directProduct(C1,C2)))) - - -Polyhedron * Polyhedron := directProduct -Polyhedron * Cone := directProduct -Cone * Polyhedron := directProduct -Cone * Cone := directProduct -Fan * Fan := directProduct - - --- PURPOSE : Computing the dual cone --- INPUT : 'C', a Cone --- OUTPUT : The dual Cone, which is {v | v*c>=0 forall c in C} -dualCone = method(TypicalValue => Cone) -dualCone Cone := C -> ( - genrays := (sort transpose C#"halfspaces",sort transpose C#"hyperplanes"); - dualgens := (sort (-(C#"rays")),sort C#"linealitySpace"); - coneBuilder(genrays,dualgens)) - - --- PURPOSE : Computing the image fan of a cone --- INPUT : '(M,C)', a Matrix 'M' and a Cone 'C' --- OUTPUT : A Fan, the common refinement of the images of all faces of --- 'C' under 'M' -imageFan = method(TypicalValue => Fan) -imageFan (Matrix,Cone) := (M,C) -> ( - M = chkZZQQ(M,"map"); - if numColumns M != ambDim C then error("The source space of the matrix must be the ambient space of the cone"); - -- Extracting data - m := numRows M; - n := dim C; - -- Compute the images of all 'm' dimensional faces and select those that are again - -- 'm' dimensional - L := apply(faces(n-m,C), e -> affineImage(M,e)); - L = select(L, e -> dim e == m); - -- Compute their common refinement - refineCones L) - - --- PURPOSE : Computing the Minkowskisum of two polyhedra in the same ambient space -minkowskiSum = method(TypicalValue => Polyhedron) - --- INPUT : '(P1,P2)', two polyhedra --- OUTPUT : The Minkowskisum as a polyhedron -minkowskiSum(Polyhedron,Polyhedron) := (P1,P2) -> ( - -- Checking for input errors - if P1#"ambient dimension" =!= P2#"ambient dimension" then error("Polyhedra must lie in the same space"); - -- Saving the vertices and rays - V1 := vertices P1; - V2 := vertices P2; - R := rays P1 | rays P2 | map(target V1,QQ^1,0); - Vnew := map(target V1,QQ^0,0); - -- Collecting all sums of vertices of P1 with vertices of P2 - Vnew = matrix transpose flatten apply(numColumns V1, i -> apply(numColumns V2, j -> flatten entries(V1_{i}+V2_{j}))); - convexHull(Vnew,R)) - - --- INPUT : '(C1,C2)', two cones --- OUTPUT : The Minkowskisum as a cone -minkowskiSum(Cone,Cone) := (C1,C2) -> ( - -- Checking for input errors - if C1#"ambient dimension" =!= C2#"ambient dimension" then error("Cones must lie in the same space"); - -- Saving the vertices and rays - R := C1#"rays" | C2#"rays"; - LS := C1#"linealitySpace" | C2#"linealitySpace"; - posHull(R,LS)) - - --- INPUT : '(C,P)', a cone and a polyhedron --- OUTPUT : The Minkowskisum as a polyhedron -minkowskiSum(Cone,Polyhedron) := (C,P) -> ( - -- Checking for input errors - if C#"ambient dimension" =!= P#"ambient dimension" then error("Cone and polyhedron must lie in the same space"); - -- Saving the vertices and rays - V := P#"vertices"; - R := P#"rays" | C#"rays" | C#"linealitySpace" | -(C#"linealitySpace"); - convexHull(V,R)) - - --- INPUT : '(P,C)', a polyhedron and a cone --- OUTPUT : The Minkowskisum as a polyhedron -minkowskiSum(Polyhedron,Cone) := (P,C) -> ( - -- Checking for input errors - if C#"ambient dimension" =!= P#"ambient dimension" then error("Cone and polyhedron must lie in the same space"); - -- Saving the vertices and rays - V := P#"vertices"; - R := P#"rays" | C#"rays" | C#"linealitySpace" | -(C#"linealitySpace"); - convexHull(V,R)) - - -Polyhedron + Polyhedron := minkowskiSum -Polyhedron + Cone := minkowskiSum -Cone + Polyhedron := minkowskiSum -Cone + Cone := minkowskiSum - --- PURPOSE : Scaling respectively the multiple Minkowski sum of a polyhedron --- INPUT : '(k,P)', where 'k' is a strictly positive rational or integer number and --- 'P' is a Polyhedron --- OUTPUT : The polyhedron 'P' scaled by 'k' -QQ * Polyhedron := (k,P) -> ( - -- Checking for input errors - if k <= 0 then error("The factor must be strictly positive"); - convexHull(k*(vertices P),rays P | linSpace P)) - -ZZ * Polyhedron := (k,P) -> promote(k,QQ) * P - - --- PURPOSE : Computing the inner normalFan of a polyhedron --- INPUT : 'P', a Polyhedron --- OUTPUT : 'F', a Fan, the inner normalFan of 'P' -normalFan = method(TypicalValue => Fan) -normalFan Polyhedron := P -> ( - -- Saving the vertices - vm := vertices P; - -- For every vertex translate P by -this vertex and take the dual cone of the positive hull of it - makeFan apply(numColumns vm, i -> (dualCone posHull affineImage(P,-vm_{i})))) - - --- PURPOSE : Computing the polar of a given polyhedron --- INPUT : 'P', a Polyhedron --- OUTPUT : A Polyhedron, the set { v | v*p<=1 forall p in P} -polar = method(TypicalValue => Polyhedron) -polar Polyhedron := P -> ( - d := P#"ambient dimension"; - -- Make the 'd'-dimensional identity - M := map(QQ^d,QQ^d,-1); - -- make the block matrix of -1 and the 'd'identity - M = (matrix{{-1_QQ}} | map(QQ^1,QQ^d,0))||(map(QQ^d,QQ^1,0) | M); - hyperA := P#"homogenizedVertices"; - hyperA = (sort (M*(hyperA#0)),hyperA#1); - verticesA := fourierMotzkin hyperA; - polyhedronBuilder(hyperA,verticesA)) - - --- PURPOSE : Computing the pyramid over the polyhedron 'P' --- INPUT : 'P', a polyhedron --- OUTPUT : A polyhedron, the convex hull of 'P', embedded into ambientdim+1 space, and the --- point (0,...,0,1) -pyramid = method(TypicalValue => Polyhedron) -pyramid Polyhedron := P -> ( - (M,LS) := P#"homogenizedVertices"; - -- Embedding into n+1 space and adding the new vertex - zerorow := map(QQ^1,source M,0); - newvertex := 1 || map(QQ^((numRows M)-1),QQ^1,0) || 1; - M = (M || zerorow) | newvertex; - LS = LS || map(QQ^1,source LS,0); - hyperA := fourierMotzkin(M,LS); - verticesA := fourierMotzkin hyperA; - polyhedronBuilder(hyperA,verticesA)) - - --- PURPOSE : Computing the sublattice basis for a given matrix of lattice points or for the lattice points --- of a given polytope -sublatticeBasis = method(TypicalValue => Matrix) - --- INPUT : 'M', a Matrix --- OUTPUT : A matrix, a basis of the sublattice spanned by the lattice points in 'M' -sublatticeBasis Matrix := M -> ( - -- Checking for input errors - M = chkZZQQ(M,"lattice points"); - M = if promote(substitute(M,ZZ),QQ) == M then substitute(M,ZZ) else error("The matrix must contain only lattice points."); - -- The sublattice is isomorphic to source mod kernel, i.e. A/K - A := source M; - K := ker M; - -- Taking minimal generators and applying M gives a basis in target M - M*(mingens (A/K))) - - --- INPUT : 'P', a polyhedron, --- OUTPUT : A matrix, a basis of the sublattice spanned by the lattice points of 'P' -sublatticeBasis Polyhedron := P -> ( - L := latticePoints P; - -- Checking for input errors - if L == {} then error("The polytope must contain lattice points."); - -- Translating 'P' so that it contains the origin if it did not already - if all(L,l -> l != 0) then L = apply(L, l -> l - L#0); - sublatticeBasis(matrix {L})) - - --- PURPOSE : Calculating the preimage of a polytope in the sublattice generated by its lattice points --- INPUT : 'P', a polyhedron --- OUTPUT : A polyhedron, the projected polyhedron, which is now normal -toSublattice = method() -toSublattice Polyhedron := P -> ( - L := latticePoints P; - -- Checking for input errors - if L == {} then error("The polytope must contain lattice points."); - b := L#0; - -- Translating 'P' so that it contains the origin if it did not already - if all(L,l -> l != 0) then L = apply(L, l -> l - L#0); - affinePreimage(sublatticeBasis matrix {L},P,b)) - - --- PURPOSE : Generating the 'd'-dimensional crosspolytope with edge length 2*'s' -crossPolytope = method(TypicalValue => Polyhedron) - --- INPUT : '(d,s)', where 'd' is a strictly positive integer, the dimension of the polytope, and 's' is --- a strictly positive rational number, the distance of the vertices to the origin --- OUTPUT : The 'd'-dimensional crosspolytope with vertex-origin distance 's' -crossPolytope(ZZ,QQ) := (d,s) -> ( - -- Checking for input errors - if d < 1 then error("dimension must at least be 1"); - if s <= 0 then error("size of the crosspolytope must be positive"); - M := map(QQ^d,QQ^d,s) | map(QQ^d,QQ^d,-s); - convexHull M) - - --- INPUT : '(d,s)', where 'd' is a strictly positive integer, the dimension of the polytope, and 's' is a --- strictly positive integer, the distance of the vertices to the origin -crossPolytope(ZZ,ZZ) := (d,s) -> crossPolytope(d,promote(s,QQ)) - - --- INPUT : 'd', where 'd' is a strictly positive integer, the dimension of the polytope -crossPolytope ZZ := d -> crossPolytope(d,1_QQ) - - --- PURPOSE : Computing the cyclic polytope of n points in QQ^d --- INPUT : '(d,n)', two positive integers --- OUTPUT : A polyhedron, the convex hull of 'n' points on the moment curve in 'd' space --- COMMENT : The moment curve is defined by t -> (t,t^2,...,t^d) in QQ^d, if we say we take 'n' points --- on the moment curve, we mean the images of 0,...,n-1 -cyclicPolytope = method(TypicalValue => Polyhedron) -cyclicPolytope(ZZ,ZZ) := (d,n) -> ( - -- Checking for input errors - if d < 1 then error("The dimension must be positive"); - if n < 1 then error("There must be a positive number of points"); - convexHull map(ZZ^d, ZZ^n, (i,j) -> j^(i+1))) - - --- PURPOSE : Computing the Ehrhart polynomial of a polytope --- INPUT : 'P', a polyhedron which must be compact, i.e. a polytope --- OUTPUT : A polynomial in QQ[x], the Ehrhart polynomial --- COMMENT : Compactness is checked within latticePoints -ehrhart = method(TypicalValue => RingElement) -ehrhart Polyhedron := P -> ( - n := dim P; - v := matrix apply(n,k -> {-1+#latticePoints( (k+1)*P)}); - M := promote(matrix apply(n,i -> reverse apply(n, j -> (i+1)^(j+1))),QQ); - M = flatten entries ((inverse M)*v); - R := QQ[x]; - 1+sum apply(n,i -> M#i * x^(n-i))) - - --- PURPOSE : Generating the empty polyhedron in n space --- INPUT : 'n', a strictly positive integer --- OUTPUT : The empty polyhedron in 'n'-space -emptyPolyhedron = method(TypicalValue => Polyhedron) -emptyPolyhedron ZZ := n -> ( - -- Checking for input errors - if n < 1 then error("The ambient dimension must be positive"); - verticesA := 2:map(QQ^(n+1),QQ^0,0); - hyperA := fourierMotzkin verticesA; - polyhedronBuilder(hyperA,verticesA)); - - - --- PURPOSE : Computing the cone of the Hirzebruch surface H_r --- INPUT : 'r' a positive integer --- OUTPUT : The Hirzebruch surface H_r -hirzebruch = method(TypicalValue => Fan) -hirzebruch ZZ := r -> ( - -- Checking for input errors - if r < 0 then error ("Input must be a positive integer"); - normalFan convexHull matrix {{0,1,0,1+r},{0,0,1,1}}) - - - --- PURPOSE : Generating the 'd'-dimensional hypercube with edge length 2*'s' -hypercube = method(TypicalValue => Polyhedron) - --- INPUT : '(d,s)', where 'd' is a strictly positive integer, the dimension of the polytope, and --- 's' is a positive rational number, half of the edge length --- OUTPUT : The 'd'-dimensional hypercube with edge length 2*'s' as a polyhedron -hypercube(ZZ,QQ) := (d,s) -> ( - -- Checking for input errors - if d < 1 then error("dimension must at least be 1"); - if s <= 0 then error("size of the hypercube must be positive"); - -- Generating half-spaces matrix and vector - intersection(map(QQ^d,QQ^d,1) || -map(QQ^d,QQ^d,1),matrix toList(2*d:{s}))) - - --- INPUT : '(d,s)', where 'd' is a strictly positive integer, the dimension of the polytope, and --- 's' is a positive integer, half of the edge length -hypercube(ZZ,ZZ) := (d,s) -> hypercube(d,promote(s,QQ)) - - --- INPUT : 'd', is a strictly positive integer, the dimension of the polytope -hypercube ZZ := d -> hypercube(d,1_QQ) - - --- PURPOSE : Computing the Newton polytope for a given polynomial --- INPUT : 'p', a RingElement --- OUTPUT : The polyhedron that has the exponent vectors of the monomials of 'p' as vertices -newtonPolytope = method(TypicalValue => Polyhedron) -newtonPolytope RingElement := p -> convexHull transpose matrix exponents p - - --- PURPOSE : Generating the positive orthant in n-space as a cone --- INPUT : 'n", a strictly positive integer --- OUTPUT : The cone that is the positive orthant in n-space -posOrthant = method(TypicalValue => Cone) -posOrthant ZZ := n -> posHull map(QQ^n,QQ^n,1) - - --- PURPOSE : Computing the state polytope of the ideal 'I' --- INPUT : 'I', a homogeneous ideal with resect to some strictly positive grading --- OUTPUT : The state polytope as a polyhedron -statePolytope = method(TypicalValue => Polyhedron) -statePolytope Ideal := I -> ( - -- Check if there exists a strictly positive grading such that 'I' is homogeneous with - -- respect to this grading - homogeneityCheck := I -> ( - -- Generate the matrix 'M' that spans the space of the differences of the - -- exponent vectors of the generators of 'I' - L := flatten entries gens I; - lt := apply(L, leadTerm); - M := matrix flatten apply(#L, i -> apply(exponents L#i, e -> (flatten exponents lt#i)-e)); - -- intersect the span of 'M' with the positive orthant - C := intersection(map(source M,source M,1),M); - -- Check if an interior vector is strictly positive - v := interiorVector C; - (all(flatten entries v, e -> e > 0),v)); - -- Compute the Groebner cone - gCone := (g,lt) -> ( - -- for a given groebner basis compute the reduced Groebner basis - -- note: might be obsolete, but until now (Jan2009) groebner bases appear to be not reduced - g = apply(flatten entries gens g, l -> ((l-leadTerm(l))% g)+leadTerm(l)); - -- collect the differences of the exponent vectors of the groebner basis - lt = flatten entries lt; - L := matrix flatten apply(#g, i -> apply(exponents g#i, e -> (flatten exponents lt#i)-e)); - -- intersect the differences - intersection L); - wLeadTerm := (w,I) -> ( - -- Compute the Groebner basis and their leading terms of 'I' with respect to the weight 'w' - R := ring I; - -- Resize w to a primitive vector in ZZ - w = flatten entries substitute((1 / gcd flatten entries w) * w,ZZ); - -- generate the new ring with weight 'w' - S := (coefficientRing R)[gens R, MonomialOrder => {Weights => w}, Global => false]; - f := map(S,R); - -- map 'I' into 'S' and compute Groebner basis and leadterm - I1 := f I; - g := gb I1; - lt := leadTerm I1; - gbRemove I1; - (g,lt)); - -- computes the symmetric difference of the two lists - sortIn := (L1,L2) -> ((a,b) := (set apply(L1,first),set apply(L2,first)); join(select(L1,i->not b#?(i#0)),select(L2,i->not a#?(i#0)))); - --Checking for homogeneity - (noError,posv) := homogeneityCheck I; - if not noError then error("The ideal must be homogeneous w.r.t. some strictly positive grading"); - -- Compute a first Groebner basis to start with - g := gb I; - lt := leadTerm I; - -- Compute the Groebner cone - C := gCone(g,lt); - gbRemove I; - -- Generate all facets of 'C' - -- Save each facet by an interior vector of it, the facet itself and the cone from - -- which it has been computed - facets := apply(faces(1,C), f -> (interiorVector f,f,C)); - --Save the leading terms as the first vertex - verts := {lt}; - -- Scan the facets - while facets != {} do ( - local omega'; - local f; - (omega',f,C) = facets#0; - -- compute an interior vector of the big cone 'C' and take a small 'eps' - omega := interiorVector C; - eps := 1/10; - omega1 := omega'-(eps*omega); - (g,lt) = wLeadTerm(omega1,I); - C' := gCone(g,lt); - -- reduce 'eps' until the Groebner cone generated by omega'-(eps*omega) is - -- adjacent to the big cone 'C' - while intersection(C,C') != f do ( - eps = eps * 1/10; - omega1 = omega'-(eps*omega); - (g,lt) = wLeadTerm(omega1,I); - C' = gCone(g,lt)); - C = C'; - -- save the new leadterms as a new vertex - verts = append(verts,lt); - -- Compute the facets of the new Groebner cone and save them in the same way as before - newfacets := faces(1,C); - newfacets = apply(newfacets, f -> (interiorVector f,f,C)); - -- Save the symmetric difference into 'facets' - facets = sortIn(facets,newfacets)); - posv = substitute(posv,ZZ); - R := ring I; - -- generate a new ring with the strictly positive grading computed by the homogeneity check - S := QQ[gens R, Degrees => entries posv]; - -- map the vertices into the new ring 'S' - verts = apply(verts, el -> (map(S,ring el)) el); - -- Compute the maximal degree of the vertices - L := flatten apply(verts, l -> flatten entries l); - d := (max apply(flatten L, degree))#0; - -- compute the vertices of the state polytope - vertmatrix := transpose matrix apply(verts, v -> ( - VI := ideal flatten entries v; - SI := S/VI; - v = flatten apply(d, i -> flatten entries basis(i+1,SI)); - flatten sum apply(v,exponents))); - -- Compute the state polytope - P := convexHull vertmatrix; - (verts,P)); - - --- PURPOSE : Generating the 'd'-dimensional standard simplex in QQ^(d+1) --- INPUT : 'd', a positive integer --- OUTPUT : The 'd'-dimensional standard simplex as a polyhedron -stdSimplex = method(TypicalValue => Polyhedron) -stdSimplex ZZ := d -> ( - -- Checking for input errors - if d < 0 then error("dimension must not be negative"); - -- Generating the standard basis - convexHull map(QQ^(d+1),QQ^(d+1),1)) - - --- PURPOSE : Saving the actual Session of Polyhedra (and PPDivisor) --- INPUT : 'F', a String, the filename --- OUTPUT : The file F ---COMMENTS : This function saves not the complete Session, but it saves every convex polyhedral objects assigned to --- a Symbol, i.e. all Cones, Polyhedra, Fans as well as Matrices and if the additional package --- "PPDivisor" is loaded it saves also all PolyhedralDivisors. Furthermore all lists and sequences --- that contain any of the types above (to arbitrary depth of lists and sequences) are also saved --- to the file. But keep in mind that this works only for such objects assigned to a Symbol! The session --- can be reovered by calling --- load F --- It is not necessary to load Polyhedra before loading the saved session, because if not yet loaded it will --- load Polyhedra. Also if PPDivisor was loaded when the session has been saved it will also be loaded. -saveSession = method() -saveSession String := F -> ( - -- Creating and opening the output file - F = openOut F; - -- Make sure Polyhedra is loaded when the session is recovered - F << "needsPackage \"Polyhedra\"" << endl; - -- Check if PPDivisor has been loaded - PPDivisorPackageLoaded := PackageDictionary#?"PPDivisor"; - if (PPDivisorPackageLoaded) then ( - -- if so, make sure it will also be loaded when the session is recovered - F << "needsPackage \"PPDivisor\"" << endl); - --Save all Matrices to the file - scan(userSymbols Matrix, s -> F << s << " = " << toExternalString value s << endl); - scan(userSymbols PolyhedralObject, s -> F << s << " = " << toExternalString value s << endl); - -- Save all Lists and Sequences containing only convex polyhedral objects and/or lists of them to the file - scan(userSymbols List | userSymbols Sequence, s -> ( - L := value s; - while L =!= flatten L do L = flatten L; - if all(L, l -> ( - if instance(l,Sequence) then all(l, e -> instance(l,PolyhedalObject) or instance(l,Matrix)) - else instance(l,PolyhedralObject) or instance(l,Matrix))) then F << s << " = " << toExternalString value s << endl))) - - - - ---------------------------------------- --- DECLARING AUXILIARY FUNCTIONS --- >> not public << ---------------------------------------- - --- PURPOSE : Building the polyhedron 'P' --- INPUT : '(hyperA,verticesA)', a pair of two matrices each describing the homogenization of P --- directly ('verticesA') and in the dual description ('hyperA') --- OUTPUT : The polyhedron 'P' -polyhedronBuilder = (hyperA,verticesA) -> ( - -- Checking if the polyhedron is empty - test := matrix join({{1}},toList((numgens target verticesA#0)-1:{0_QQ})); - if (((transpose(verticesA#0))*test == 0) and ((transpose(verticesA#1))*test == 0)) then ( - zeromap := map(target verticesA#0,QQ^0,0); - verticesA = (zeromap,zeromap); - hyperA = fourierMotzkin verticesA); - -- Sorting into vertices and rays - VR := verticesA#0; - B := map(target VR,QQ^0,0); - C := B; - VRpart := partition(n -> VR_n_0 =!= 0_QQ,toList(0..(numColumns VR)-1)); - if VRpart#?true then ( - B = VR_(VRpart#true); - B = matrix transpose apply(numColumns B, j -> flatten entries((1/B_j_0)*B_{j}))); - if VRpart#?false then C = VR_(VRpart#false); - --B = B_{1..(numgens source B)-1}; - --C = C_{1..(numgens source C)-1}; - -- Elimination of the trivial half-space - test = matrix join({{-1}},toList((numgens target (hyperA#0))-1:{0_QQ})); - H := transpose (hyperA#0)_(toList select(0..(numColumns hyperA#0)-1, i -> test =!= (hyperA#0)_{i})); - -- Determine the lineality space - LS := verticesA#1; - LS = LS^{1..(numgens target LS)-1}; - -- Determine the defining hyperplanes - HP := transpose(hyperA#1); - HP = (HP_{1..(numgens source HP)-1},-HP_{0}); - -- Defining the Polyhedron - new Polyhedron from { - "ambient dimension" => (numgens target B)-1, - "dimension of polyhedron" => ((numgens target B)-1)-(rank(hyperA#1)), - "dimension of lineality space" => numgens source LS, - "linealitySpace" => LS, - "number of vertices" => numgens source B, - "number of rays" => numgens source C, - "vertices" => B^{1..(numgens target B)-1}, - "rays" => C^{1..(numgens target C)-1}, - "number of facets" => numgens target H, - "halfspaces" => (H_{1..(numgens source H)-1},-H_{0}), - "hyperplanes" => HP, - "homogenizedVertices" => verticesA, - "homogenizedHalfspaces" => hyperA}) - - --- PURPOSE : Building the Cone 'C' --- INPUT : '(genrays,dualgens)', a pair of two matrices each describing the cone C --- directly as generating rays ('genrays') and in the --- dual description as intersection of half-spaces through --- the origin ('dualgens') --- OUTPUT : The Cone 'C' -coneBuilder = (genrays,dualgens) -> ( - -- Sorting into rays, lineality space generators, supporting half-spaces, and hyperplanes - RM := genrays#0; - LS := genrays#1; - HS := transpose(-dualgens#0); - HP := transpose(dualgens#1); - -- Defining C - new Cone from { - "ambient dimension" => numgens target RM, - "dimension of the cone" => (numgens target RM)-(rank HP), - "dimension of lineality space" => numgens source LS, - "linealitySpace" => LS, - "number of rays" => numgens source RM, - "rays" => RM, - "number of facets" => numgens target HS, - "halfspaces" => HS, - "hyperplanes" => HP, - "genrays" => genrays, - "dualgens" => dualgens}) - - --- PURPOSE : check whether a matrix os over ZZ or QQ --- INPUT : '(M,msg)', a matrix 'M' and a string 'msg' --- OUTPUT : the matrix 'M' promoted to QQ if it was over ZZ or QQ, otherwise an error -chkZZQQ = (M,msg) -> ( - R := ring M; - if R =!= ZZ and R =!= QQ then error("expected matrix of ",msg," to be over ZZ or QQ"); - promote(M,QQ)); - - --- PURPOSE : Computing the Hilbert basis of a standardised cone (project and lift algorithm --- INPUT : 'A' a matrix, the row echolon form of the defining half-spaces of the cone --- OUTPUT : a list of one column matrices, the generators of the cone over A intersected with --- the positive orthant -constructHilbertBasis = A -> ( - -- Defining the function to determine if u is lower v - lowvec := (u,v) -> ( - n := (numRows u)-1; - diffvec := flatten entries(u-v); - if all(diffvec, i -> i <= 0) then abs(u_(n,0)) <= abs(v_(n,0)) and (u_(n,0))*(v_(n,0)) >= 0 - else false); - -- Collecting data - A = substitute(A,ZZ); - H := {A^{0}_{0}}; - s := numRows A; - n := numColumns A; - --doing the project and lift algorithm step by step with increasing dimensions - scan(n-1, i -> ( - -- the set 'F' will contain the lifted basis vectors, 'B' are the first i+2 columns of 'A' as a rowmatrix, - -- the set 'H' contains the vectors from the last loop that are one dimension smaller - F := {}; - B := transpose A_{0..(i+1)}; - -- Decide between lifting the existing vectors (i > s-1) or also adding the next column of 'B' - if i < s-1 then ( - -- Lifting the existing vectors from 'H' - F = apply(H, h -> ( - j := 0; - while numRows h == i+1 do ( - if isSubset(image(h || matrix{{j}}), image B) then h = (h || matrix{{j}}); - j = j+1); - h)); - -- Adding +- times the next column of 'B' - F = join(F,{B_{i+1}^{0..(i+1)},-B_{i+1}^{0..(i+1)}})) - else ( - -- Lifting the existing vectors from 'H' - nullmap := map(ZZ^1,ZZ^s,0); - nullvec := map(ZZ^1,ZZ^1,0); - F = apply(H, h -> B*substitute(vertices intersection(nullmap,nullvec,B^{0..i},h),ZZ))); - -- Computing the S-pairs from the elements of 'F' and saving them in 'C' - C := select(subsets(#F,2), j -> ( - f := F#(j#0); - g := F#(j#1); - (f_(i+1,0))*(g_(i+1,0)) < 0 and f+g != 0*(f+g))); - C = apply(C, j -> F#(j#0)+F#(j#1)); - -- The elements of 'F' are saved in 'G' - G := F; - j := 0; - -- Adding those elements of 'C' to 'G' that satisfy the "normalform" condition by increasing last entry - while C != {} do ( - Cnow := partition(e -> sum drop(flatten entries e,-1) == j,C); - C = if Cnow#?false then Cnow#false else {}; - Cnow = if Cnow#?true then select(Cnow#true, f -> all(G, g -> not lowvec(g,f))) else {}; - Cnew := flatten apply(Cnow, f -> apply(select(G, g -> f_(i+1,0)*g_(i+1,0) < 0 and f+g != 0*(f+g)), g -> f+g)); - if all(Cnew, e -> sum drop(flatten entries e,-1) != j) then j = j+1; - C = unique (C | Cnew); - G = unique (G | Cnow)); - -- saving those elements of 'G' with positive last entry into 'H' - H = select(G, g -> g_(i+1,0) >= 0))); - H) - - - --- PURPOSE : select those cones in a list that do not contain any other cone of the list --- INPUT : 'L', a list of cones --- OUTPUT : The list of cones that don't contain any of the other -inclMinCones = L -> ( - newL := {}; - -- Scanning the list - while L != {} do ( - C := L#0; - L = drop(L,1); - -- check, if 'C' contains any cone remaining in - if all(L, C1 -> not contains(C,C1)) then ( - -- if not, then check if 'C' contains any of the cones already in the final list - if all(newL, C1 -> not contains(C,C1)) then ( - -- if not again, then add 'C' to the final list. - newL = newL | {C}))); - newL); - - --- PURPOSE : intersect every face in L with every facet in F and return the inclusion maximal intersections that --- are not equal to one element in L --- INPUT : 'L', a list of Sequences each containing a set of vertices and a set of rays giving the faces of a --- certain dimension of a polyhedron --- 'F', a list of Sequences each containing a set of vertices and a set of rays giving the facets --- of the same polyhedron --- OUTPUT : a list of Sequences each containing a set of vertices and a set of rays giving the faces --- of the same polyhedron one dimension lower then the ones in 'L' -intersectionWithFacets = (L,F) -> ( - -- Function to check if 'e' has at least one vertex and is not equal to 'l' - isValid := (e,l) -> if e#0 =!= set{} then e =!= l else false; - newL := {}; - -- Intersecting each element of 'L' with each element of 'F' - scan(L, l -> ( - scan(F, f -> ( - e := ((l#0)*(f#0),(l#1)*(f#1)); - -- if the intersection is valid add it to newL if it is not contained in one of the elements - -- already in newL and remove those contained in 'e' - if isValid(e,l) then ( - if not any(newL, g -> isSubset(e#0,g#0) and isSubset(e#1,g#1)) then ( - newL = select(newL, g -> not (isSubset(g#0,e#0) and isSubset(g#1,e#1)))|{e})))))); - newL); - - --- PURPOSE : intersect every face in L with every facet in F and return the inclusion maximal intersections that --- are not equal to one element in L --- INPUT : 'L', a list of sets each containing the rays of the faces of a certain dimension of a polyhedron --- 'F', a list of sets each containing the rays of the facets of the same polyhedron --- OUTPUT : a list of sets each containing the rays of the faces of the same polyhedron one dimension lower --- then the ones in 'L' -intersectionWithFacetsCone = (L,F) -> ( - -- Function to check if 'e' has at least one vertex and is not equal to 'l' - isValid := (e,l) -> if e =!= set{} then e =!= l else false; - newL := {}; - -- Intersecting each element of 'L' with each element of 'F' - scan(L, l -> ( - scan(F, f -> ( - e := l*f; - -- if the intersection is valid add it to newL if it is not contained in one of the elements - -- already in newL and remove those contained in 'e' - if isValid(e,l) then ( - if not any(newL, g -> isSubset(e,g)) then ( - newL = select(newL, g -> not isSubset(g,e))|{e})))))); - newL); - - --- PURPOSE : Computes the common refinement of a list of cones --- INPUT : 'L', a list of cones --- OUTPUT : A fan, the common refinement of the cones -refineCones = L -> ( - -- Collecting the rays of all cones - R := rays L#0; - n := numRows R; - R = apply(numColumns R, i -> R_{i}); - L1 := drop(L,1); - R = unique flatten (R | apply(L1, C -> apply(numColumns rays C, i -> (rays C)_{i}))); - -- Writing the rays into one matrix - M := matrix transpose apply(R, r -> flatten entries r); - -- Compute the coarsest common refinement of these rays - F := ccRefinement M; - -- Collect for each cone of the ccRef the intersection of all original cones, that contain - -- the interior of that cone - makeFan apply(genCones F, C -> ( - v := interiorVector(C); - intersection select(L, c -> contains(c,v))))) - - ---------------------------------------- --- DOCUMENTATION ---------------------------------------- - - -beginDocumentation() - -document { - Key => Polyhedra, - Headline => "for computations with convex polyhedra, cones, and fans", - - "A rational convex ", TO Polyhedron, " is the intersection of finitely many affine half-spaces - over ", TO QQ, " or equivalently, the convex hull of a finite set of vertices and rays. - A rational convex polyhedral ", TO Cone, " is the intersection of finitely many linear half-spaces - over ", TO QQ, " or equivalently, the positive hull of a finite set of rays. A ", TO Fan, " is - a finite collection of cones such that for each cone all its faces are in the fan and for two cones - in the fan the intersection is a face of each.", - - PARA{}, TT "Polyhedra", " uses the ", TO FourierMotzkin, " package by ", - HREF("http://www.mast.queensu.ca/~ggsmith", "Gregory G. Smith"), ". Each polyhedron or cone is - saved in both descriptions and a fan is saved as the list of its generating cones.", - - PARA{}, "Here are some examples illustrating the main uses of this package.", - UL { - {TO "Working with polyhedra"}, - {TO "Working with cones"}, - {TO "Working with fans"} - }, - - PARA{}, "For an introduction to polyhedra and cones, we recommend ", - HREF("http://www.math.tu-berlin.de/~ziegler/", "Gunter - M. Ziegler's"), " ", EM "Lectures on Polytopes", ", Graduate - Texts in Mathematics 152, Springer-Verlag, New York, 1995.", - - PARA{}, "The author would like to thank ",HREF("http://people.cs.uchicago.edu/~nilten/", "Nathan Ilten")," - for contributing several functions to the package." - - } - -document { - Key => "Working with polyhedra", - - "We start with a polyhedron in 2-space which is the ",TO convexHull," of a given set of points.", - - EXAMPLE { - " V = matrix {{0,2,-2,0},{-1,1,1,1}}", - " P = convexHull V" - }, - - PARA{}, "This gives an overview of the characteristics of the polyhedron. If we want to know - more details, we can ask for them.", - - EXAMPLE { - " vertices P" - }, - - PARA{}, "Here we see that the point (0,1) is not a vertex and ",TT "P"," is actually a triangle.", - - EXAMPLE { - " (HS,v) = halfspaces P" - }, - - PARA{}, "This gives the defining affine half-spaces, i.e. ",TT "P"," is given by all ",TT "p"," such - that ",TT "HS*p =< v"," and that lie in the defining affine hyperplanes. To get the hyperplanes we use:", - - EXAMPLE { - " hyperplanes P" - }, - - PARA{}, "There are none, so the polyhedron is of full dimension. It is also compact, since ",TT "P"," has - no rays and the lineality space is of dimension zero.", - - EXAMPLE { - " rays P", - " linSpace P" - }, - - PARA{}, "Furthermore, we can construct the convex hull of a set of points and a set of rays.", - - EXAMPLE { - " R = matrix {{1},{0},{0}}", - " V1 = V || matrix {{1,1,1,1}}", - " P1 = convexHull(V1,R)", - " vertices P1" - }, - - PARA{}, "This polyhedron is not compact anymore and also not of full dimension.", - - EXAMPLE { - " rays P1", - " hyperplanes P1" - }, - - PARA{}, "On the other hand we can construct a polyhedron as the ",TO intersection," of affine - half-spaces and affine hyperplanes.", - - EXAMPLE { - " HS = transpose (V || matrix {{-1,2,0,1}})", - " v = matrix {{1},{1},{1},{1}}", - " HP = matrix {{1,1,1}}", - " w = matrix {{3}}", - " P2 = intersection(HS,v,HP,w)" - }, - - PARA{}, "This is a triangle in 3-space with the following vertices.", - - EXAMPLE { - " vertices P2" - }, - - PARA{}, "If we don't intersect with the hyperplane we get a full dimensional polyhedron.", - - EXAMPLE { - " P3 = intersection(HS,v)", - " vertices P3", - " linSpace P3" - }, - - PARA{}, "Note that the vertices are given modulo the lineality space. Besides constructing - polyhedra by hand, there are also some basic polyhedra implemented such as - the ",TO hypercube,", in this case with edge-length four.", - - EXAMPLE { - " P4 = hypercube(3,2)", - " vertices P4" - }, - - PARA{}, "Another on is the ",TO crossPolytope,", in this case with diameter six. ", - - EXAMPLE { - " P5 = crossPolytope(3,3)", - " vertices P5" - }, - - PARA{}, "Furthermore the standard simplex (",TO stdSimplex,").", - - EXAMPLE { - " P6 = stdSimplex 2", - " vertices P6" - }, - - PARA{}, "Now that we can construct polyhedra, we can turn to the functions - that can be applied to polyhedra. First of all, we can apply the ",TO convexHull," - function also to a pair of polyhedra:", - - EXAMPLE { - " P7 = convexHull(P4,P5)", - " vertices P7" - }, - - PARA{}, "Or we can intersect them by using ",TO intersection,":", - - EXAMPLE { - " P8 = intersection(P4,P5)", - " vertices P8" - }, - - PARA{}, "Furthermore, both functions can be applied to a list containing any number - of polyhedra and matrices defining vertices/rays or affine half-spaces/hyperplanes. - All of these must be in the same ambient space. For example:", - - EXAMPLE { - " P9 = convexHull {(V1,R),P2,P6}", - " vertices P9" - }, - - PARA{}, "Further functions are for example the Minkowski sum (",TO minkowskiSum,") of - two polyhedra.", - - EXAMPLE { - " Q = convexHull (-V)", - " P10 = P + Q", - " vertices P10" - }, - - PARA{}, "In the other direction, we can also determine all Minkowski summands - (see ",TO minkSummandCone,") of a polyhedron.", - - EXAMPLE { - " (C,L,M) = minkSummandCone P10", - " apply(values L, vertices)" - }, - - PARA{}, "Here the polyhedra in the hash table ",TT "L"," are all possible Minkowski - summands up to scalar multiplication and the columns of ",TT "M"," give the minimal - decompositions. So the hexagon ",TT "P10"," is not only the sum of two triangles but also the sum - of three lines. Furthermore, we can take the direct product of two polyhedra.", - - EXAMPLE { - " P11 = P * Q", - " vertices P11" - }, - - PARA{}, "The result is in QQ^4.", - - EXAMPLE { - "ambDim P11" - }, - - PARA{}, "To find out more about this polyhedron use for example.", - - EXAMPLE { - " fVector P11" - }, - - PARA{}, "The function ",TO fVector," gives the number of faces of each dimension, so it has 9 - vertices, 18 edges and so on. We can access the faces of a certain codimension via:", - - EXAMPLE { - " L = faces(1,P11)", - " apply(L,vertices)" - }, - - PARA{}, "We can compute all lattice points of the polyhedron with ",TO latticePoints,".", - - EXAMPLE { - " L = latticePoints P11", - " #L" - }, - - PARA{}, "Evenmore the tail/recession cone of a polyhedron with ",TO tailCone,".", - - EXAMPLE { - " C = tailCone P1", - " rays C" - }, - - PARA{}, "Finally, there is also a function to compute the polar of a - polyhedron, i.e. all points in the dual space that are greater than -1 on - all points of the polyhedron:", - - EXAMPLE { - " P12 = polar P11", - " vertices P12" - } - } - -document { - Key => "Working with cones", - - "We start with a cone in 2-space which is the positive hull (",TO posHull,") of a given set of rays.", - - EXAMPLE { - " R = matrix {{1,1,2},{2,1,1}}", - " C = posHull R", - " ambDim C" - }, - - PARA{}, "This gives an overview of the characteristics of the cone. If we want to know - more details, we can ask for them.", - - EXAMPLE { - " rays C" - }, - - PARA{}, "Using ",TO rays," we see that (1,1) is not an extremal ray of the cone.", - - EXAMPLE { - " HS = halfspaces C" - }, - - PARA{}, "The function ",TO halfspaces," gives the defining linear half-spaces, i.e. ",TT "C"," is given by all ",TT "p"," in - the defining linear hyperplanes that satisfy ",TT "HS*p >= 0",". But in this case there are none, so the polyhedron is of full - dimension. Furthermore, we can construct the positive hull of a set of rays and a linear subspace.", - - EXAMPLE { - " R1 = R || matrix {{0,0,0}}", - " LS = matrix {{1},{1},{1}}", - " C1 = posHull(R1,LS)", - " rays C1" - }, - - PARA{}, "Note that the rays are given modulo the lineality space. On the other hand we can - construct cones as the ",TO intersection," of linear half-spaces and hyperplanes.", - - EXAMPLE { - " HS = transpose R1", - " HP = matrix {{1,1,1}}", - " C2 = intersection(HS,HP)" - }, - - PARA{}, "This is a two dimensional cone in 3-space with the following rays:", - - EXAMPLE { - " rays C2" - }, - - PARA{}, "If we don't intersect with the hyperplane we get a full dimensional cone.", - - EXAMPLE { - " C3 = intersection HS", - " rays C3", - " linSpace C3" - }, - - PARA{}, "Again, the rays are given modulo the lineality space. Also, one can use - given cones, for example the positive orthant (",TO posOrthant,"):", - - EXAMPLE { - " C4 = posOrthant 3", - " rays C4" - }, - - PARA{}, "Now that we can construct cones, we can turn to the functions - that can be applied to cones. First of all, we can apply the ",TO intersection," - function also to a pair of cones in the same ambient space:", - - EXAMPLE { - " C5 = intersection(C1,C2)", - " rays C5" - }, - - PARA{}, "On the other hand, we can take their positive hull by using ",TO posHull,":", - - EXAMPLE { - " C6 = posHull(C1,C2)", - " rays C6", - " linSpace C6" - }, - - PARA{}, "Furthermore, both functions (",TO intersection," and ",TO posHull,") can - be applied to a list containing any number of cones and matrices defining - rays and lineality space or linear half-spaces and hyperplanes. These must be in the - same ambient space. For example:", - - EXAMPLE { - " R2 = matrix {{2,-1},{-1,2},{-1,-1}}", - " C7 = posHull {R2,C3,C4}", - " rays C7", - " linSpace C7" - }, - - PARA{}, "Since they are all cones their positive hull is the same as their - Minkowski sum, so in fact:", - - EXAMPLE { - " C6 == C1 + C2" - }, - - PARA{}, "But we can take the Minkowski sum of a cone and a polyhedron. For this, - both objects must lie in the same ambient space and the resulting object is then - a polyhedron:", - - EXAMPLE { - " P = crossPolytope 3", - " P1 = C6 + P", - " (vertices P1,rays P1)" - }, - - PARA{}, "Furthermore, we can take the direct product (",TO directProduct,") of - two cones.", - - EXAMPLE { - " C8 = C * C1", - " rays C8", - " linSpace C8" - }, - - PARA{}, "The result is in QQ^5.", - - EXAMPLE { - "ambDim C8" - }, - - PARA{}, "To find out more about this cone use for example ",TO fVector,":", - - EXAMPLE { - " fVector C8" - }, - - PARA{}, "This function gives the number of faces of each dimension, so it has 1 - vertex, the origin, 1 line, 4 two dimensional faces and so on. We can access the - faces of a certain codimension via ",TO faces,":", - - EXAMPLE { - " L = faces(1,C8)", - " apply(L,rays)" - }, - - PARA{}, "We can also check if the cone is smooth:", - - EXAMPLE { - " isSmooth C8" - }, - - PARA{}, "Evenmore we can compute the Hilbert basis of the cone with ",TO hilbertBasis,".", - - EXAMPLE { - " L = hilbertBasis C8", - " #L" - }, - - PARA{}, "Finally, there is also a function to compute the dual cone, i.e. - the set of all points in the dual space that are positive on the cone.", - - EXAMPLE { - " C9 = dualCone C8", - " rays C9" - } - - } - -document { - Key => "Working with fans", - - "We start by constructing a fan, which consists of a single cone and all of its - faces:", - - EXAMPLE { - " C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}", - " F = makeFan C" - }, - - PARA{}, "By this, we have already constructed the fan consisting of the - positive orthant and all of its faces. The package saves the generating cones - of the fan, which can be accessed by:", - - EXAMPLE { - "genCones F" - }, - - PARA{}, "Now we could expand the fan by adding more cones, for example the following:", - - EXAMPLE { - " C1 = posHull matrix {{1,0,0},{1,1,0},{0,0,-1}}" - }, - - PARA{}, "But in this case we can not, because the two cones are not compatible, - i.e. their intersection is not a face of each. So, when one tries to add a cone - to a fan that is not compatible with one of the generating cones of the fan, the - function ",TO addCone," gives an error. For two cones one can - check if their intersection is a common face by using ",TO commonFace,":", - - EXAMPLE { - " commonFace(C,C1)" - }, - - PARA{}, "Since the intersection of both is already computed in this function - there is a different function, which also returns the intersection, to save - computation time when one needs the intersection afterward anyway:", - - EXAMPLE { - " (b,C2) = areCompatible(C,C1)", - " rays C2" - }, - - PARA{}, "So we can make the cone compatible and add it to the fan.", - - EXAMPLE { - " C1 = posHull matrix {{1,0,0},{0,1,0},{0,0,-1}}", - " F = addCone(C1,F)" - }, - - PARA{}, "Instead of creating a fan with one cone and then adding more cones, we - can also make a fan out of a list of cones:", - - EXAMPLE { - " C2 = posHull matrix {{-1,0,0},{0,1,0},{0,0,1}};", - " C3 = posHull matrix {{-1,0,0},{0,1,0},{0,0,-1}};", - " C4 = posHull matrix {{-1,0,0},{0,-1,0},{0,0,1}};", - " C5 = posHull matrix {{-1,0,0},{0,-1,0},{0,0,-1}};", - " F1 = makeFan {C2,C3,C4,C5}" - }, - - PARA{}, "Furthermore, we could add a list of cones to an existing fan:", - - EXAMPLE { - " C6 = posHull matrix {{1,0,0},{0,-1,0},{0,0,1}};", - " C7 = posHull matrix {{1,0,0},{0,-1,0},{0,0,-1}};", - " F1 = addCone( {C6,C7}, F1)", - }, - - PARA{}, "Finally, we can add a whole fan to another fan:", - - EXAMPLE { - " F1 = addCone(F,F1)" - }, - - PARA{}, "So, ",TO makeFan," and ",TO addCone," are the methods to construct - fans ''from scratch'', but there are also methods to get fans directly, for example ",TO normalFan,", - which constructs the inner normal fan of a polytope.", - - EXAMPLE { - " P = hypercube 4", - " F2 = normalFan P" - }, - - PARA{}, "Now we have seen how to construct fans, so we turn to functions on fans, - for example the direct product (",TO directProduct,":", - - EXAMPLE { - " F3 = makeFan {posHull matrix {{1}},posHull matrix {{-1}}}", - " F1 = F3 * F1"}, - - PARA{}, "The result is in the direct product of the ambient spaces.", - - EXAMPLE { - " ambDim F1" - }, - - PARA{}, "Of course, we can check if two fans are the same:", - - EXAMPLE { - " F1 == F2" - }, - - PARA{}, "A bit more on fans can be found in part 2: ",TO "Working with fans - Part 2","." - - } - -document { - Key => "Working with fans - Part 2", - - "Now we construct a new fan to show some other functions.", - - EXAMPLE { - " C1 = posHull matrix {{1,1,-1,-1},{1,-1,1,-1},{1,1,1,1}};", - " C2 = posHull matrix {{1,1,1},{0,1,-1},{-1,1,1}};", - " C3 = posHull matrix {{-1,-1,-1},{0,1,-1},{-1,1,1}};", - " C4 = posHull matrix {{1,-1},{0,0},{-1,-1}};", - " F = makeFan {C1,C2,C3,C4}" - }, - - PARA{}, "This is not a ''very nice'' fan, as it is neither complete nor - of pure dimension:", - - EXAMPLE { - " isComplete F", - " isPure F" - }, - - PARA{}, "If we add two more cones the fan becomes complete.", - - EXAMPLE { - " C5 = posHull matrix {{1,-1,1,-1},{-1,-1,0,0},{1,1,-1,-1}};", - " C6 = posHull matrix {{1,-1,1,-1},{1,1,0,0},{1,1,-1,-1}};", - " F = addCone({C5,C6},F)", - " isComplete F" - }, - - PARA{}, "For a complete fan we can check if it is projective:", - - EXAMPLE { - " isProjective F" - }, - - PARA{}, "If the fan is projective, the function returns a polyhedron such that - the fan is its normal fan, otherwise it returns the empty polyhedron. This means - our fan is projective." - - } - -document { - Key => PolyhedralObject, - Headline => "the class of all polyhedral objects in Polyhedra", - - TT "PolyhedralObject"," is the parent class of the three polyhedral objects in Polyhedra:", - - UL { - {TO "Polyhedron"}, - {TO "Cone"}, - {TO "Fan"} - }, - - EXAMPLE { - " convexHull matrix {{1,1,0,0},{1,0,1,0}}", - " posHull matrix {{1,2},{2,1}}", - " hirzebruch 3" - } - - } - -document { - Key => Polyhedron, - Headline => "the class of all convex polyhedra", - - "A Polyhedron represents a rational polyhedron. It can be bounded or unbounded, - need not be full dimensional or may contain a proper affine subspace. It can - be empty or zero dimensional. It is saved as a hash table which contains - the vertices, generating rays, and the basis of the lineality space of the - Polyhedron as well as the defining affine half-spaces and hyperplanes. The - output of a Polyhedron looks like this:", - - EXAMPLE { - " convexHull(matrix {{0,0,-1,-1},{2,-2,1,-1},{0,0,0,0}},matrix {{1},{0},{0}})", - }, - - PARA{}, "This table displays a short summary of the properties of the Polyhedron. - Note that the number of rays and vertices are modulo the lineality space. So - for example a line in QQ^2 has one vertex and no rays. However, one can not - access the above information directly, because this is just a virtual hash table - generated for the output. The data defining a Polyhedron is extracted - by the functions included in this package. A Polyhedron can be constructed as - the convex hull (",TO convexHull,") of a set of points and a set of rays or as the - intersection (",TO intersection,") of a set of affine half-spaces and affine hyperplanes.", - - PARA{}, "For example, consider the square and the square with an emerging ray - for the convex hull:", - - EXAMPLE { - " V = matrix {{1,1,-1,-1},{1,-1,1,-1}}", - " convexHull V", - " R = matrix {{1},{1}}", - " convexHull(V,R)" - }, - - PARA{}, "If we take the intersection of the half-spaces defined by the directions of the - vertices and 1 we get the crosspolytope:", - - EXAMPLE { - " HS = transpose V", - " v = R || R", - " P = intersection(HS,v)", - " vertices P" - }, - - PARA{}, "This can for example be embedded in 3-space on height 1:", - - EXAMPLE { - " HS = HS | matrix {{0},{0},{0},{0}}", - " HP = matrix {{0,0,1}}", - " w = matrix {{1}}", - " P = intersection(HS,v,HP,w)", - " vertices P" - }, - - PARA{}, "See also ",TO "Working with polyhedra","." - - } - -document { - Key => Cone, - Headline => "the class of all rational convex polyhedral cones", - - "A Cone represents a rational convex polyhedral cone. It need not be full - dimensional or may contain a proper linear subspace. It can be zero - dimensional, i.e. the origin. It is saved as a hash table which - contains the generating rays and the basis of the lineality space of the - cone as well as the defining half-spaces and hyperplanes. The output of a - Cone looks like this:", - - EXAMPLE { - " posHull matrix {{0,0,-1,-1,1},{2,-2,1,-1,0},{1,1,1,1,0}}", - }, - - PARA{}, "This table displays a short summary of the properties of the Cone. The number - of rays is modulo the lineality space. However, one can not access the above information - directly, because this is just a virtual hash table generated for the output. The data - describing a Cone is extracted by the functions included in this package. A Cone - can be constructed as the positive hull (",TO posHull,")of a set of rays or as the intersection - (",TO intersection,") of a set of linear half-spaces and linear hyperplanes.", - - PARA{}, "As examples for the positive hull consider the following cones:", - - EXAMPLE { - " R = matrix{{1,2,3,1},{2,3,1,1},{3,1,2,1}}", - " C = posHull R", - " rays C", - " LS = matrix{{1},{1},{-2}}", - " C = posHull(R,LS)", - " rays C" - }, - - PARA{}, "On the other hand, we can use these matrices as defining half-spaces and hyperplanes - for the intersection:", - - EXAMPLE { - " HS = transpose R", - " C = intersection HS", - " rays C", - " HP = transpose LS", - " C = intersection(HS,HP)", - " rays C" - }, - - PARA{}, "See also",TO "Working with cones","." - - } - -document { - Key => Fan, - Headline => "the class of all fans", - - "A Fan represents a fan of rational convex polyhedral cones, i.e. a collection of cones, - such that for every cone in the fan all faces are in the fan and for every two cones in - the fan their intersection is a face of each (intersection condition). - It need not be full dimensional or pure, and the cones need not be pointed. It is saved - as a hash table which contains a list of the generating cones of the fan starting - with those of maximal dimension. So for every cone in this list all faces are considered - to be in the fan. The output of a Fan looks like this:", - - EXAMPLE { - " normalFan crossPolytope 3", - }, - - PARA{}, "This table displays a short summary of the properties of the Fan. - However, one can not access the above information directly, because this - is just a virtual hash table generated for the output. The data defining a Fan - is extracted by the functions included in this package. A Fan can be constructed by - collecting Cones that satisfy the intersection condition. Every cone that is added to - a Fan is always considered as the collection of the Cone and all of its faces.", - - EXAMPLE { - " C1 = posHull matrix {{2,2},{1,-1}};", - " C2 = posHull matrix {{2,-2},{1,1}};", - " C3 = posHull matrix {{-2,-2},{1,-1}};", - " C4 = posHull matrix {{-2,2},{-1,-1}};", - " F = makeFan {C1,C2,C3,C4}" - }, - - PARA{}, "This fan is for example the normal fan of a ''flattened'' crosspolytope in 2-space.", - - PARA{}, " See also ",TO "Working with fans","." - - } - -document { - Key => {convexHull, (convexHull,Matrix), (convexHull,Matrix,Matrix), - (convexHull,Polyhedron,Polyhedron), (convexHull,List)}, - Headline => "computing the convex hull of points, rays and polyhedra", - Usage => " P = convexHull M \nP = convexHull(M,N) \nP = convexHull(P1,P2) \nP = convexHull L", - Inputs => { - "M" => Matrix => {"with entries in", TO ZZ," or ", TO QQ}, - "N" => Matrix => {"with entries in", TO ZZ," or ", TO QQ}, - "P1" => Polyhedron, - "P2" => Polyhedron, - "L" => List - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, TT "convexHull", " computes the convex hull of the input. - In the first two cases it considers the columns of ", TT "M", " - as a set of points and the columns of ", TT "N", " (if given) as - a set of rays and computes the polyhedron that is the convex hull - of the points plus the rays. The two matrices must have the same - number of rows, i.e. the columns must lie in the same ambient space. - If ", TT "N", " is not given or equal to 0, then the resulting - polyhedron is compact and hence a polytope. The points need not - be the vertices of the polyhedron. In the third case it computes - the convex hull of ", TT "P1", " and ", TT "P2", " if they lie - in the same ambient space. Finally, it computes the convex hull - of a list ", TT "L"," where the list may contain a combination - of the following in any order.", - - UL { - {"Vertices, given by a matrix ", TT "M", " over ", TO ZZ, " - or ", TO QQ}, - {"Vertices and rays, given by a sequence ", TT "(V,R)", "of two - matrices over ", TO ZZ, " or ", TO QQ}, - {TO Cone}, - {TO Polyhedron} - }, - - PARA{}, "Then ", TT "convexHull", " computes the convex hull of all - inserted objects, if they are in the same ambient space, i.e. all matrices - must have the same number of rows, which must equal the ambient dimension - of all cones and polyhedra.", - - PARA{}, "For example, consider the square in ",TO QQ,"^2:", - - EXAMPLE { - " M = matrix {{1,1,-1,-1},{1,-1,1,-1}}", - " P = convexHull M" - }, - - PARA{}, "If we add a ray, then it is not compact anymore:", - - EXAMPLE { - " r = matrix {{1},{2}}", - " P =convexHull(M,r)" - }, - - PARA{}, "If we add some more vertices to ",TT "M"," then we get a hexagon:", - - EXAMPLE { - " N = matrix {{-2,-2,0},{0,-2,-2}}", - " Q = convexHull(M|N)" - }, - - PARA{}, "Again if we add the ray ",TT "r"," then the polyhedron is not compact:", - - EXAMPLE { - " Q1 = convexHull(M|N,r)" - }, - - PARA{}, "To get this polyhedron we could also have used the application of ",TT "convexHull"," - to lists or pairs of polyhedra:", - - EXAMPLE { - " P1 = convexHull {P,N}", - " P1 == Q1", - " P1 = convexHull(P,Q)", - " P1 == Q1" - } - } - -document { - Key => {posHull, (posHull,Cone,Cone), (posHull,Matrix), (posHull,Matrix,Matrix), (posHull,Polyhedron), - (posHull,List)}, - Headline => "computes the positive hull of rays, cones, and the cone over a polyhedron", - Usage => " C = posHull M \nC = posHull(M,N) \nC = posHull(C1,C2) \nC = posHull P \nC = posHull L", - Inputs => { - "M" => Matrix => {"with entries in", TO ZZ," or ", TO QQ}, - "N" => Matrix => {"with entries in", TO ZZ," or ", TO QQ}, - "C1" => Cone, - "C2" => Cone, - "P" => Polyhedron, - "L" => List - }, - Outputs => { - "C" => Cone - }, - - PARA{}, TT "posHull", " computes the positive hull of the input. In the - first two cases it considers the columns of ", TT "M", " as a set of rays - and the columns of ", TT "N", " (if given) as generators of the lineality - space and computes the cone that is the positive hull of the rays plus - the lineality space. The two matrices must have the same number of rows, - i.e. the columns must lie in the same ambient space. If ", TT "N", " is - not given or equal to 0 then the resulting cone is pointed. The rays need - not be a minimal generating set of the cone. If two cones are inserted it - computes their positive hull if they lie in the same ambient space. In the - case of a polyhedron it computes the cone given by all positive multiples - of points of the polyhedron. If applied to a list, it may contain a - combination of the following in any order.", - - UL { - {"Rays, given by a matrix ", TT "R", " over ", TO ZZ, " - or ", TO QQ}, - {"Rays and a lineality space, given by a sequence ", TT "(R,LS)", " of two - matrices over ", TO ZZ, " or ", TO QQ}, - {TO Cone}, - {TO Polyhedron} - }, - - PARA{}, "Then ", TT "posHull", " computes the positive hull of all - inserted objects, if they are in the same ambient space, i.e. all matrices - must have the same number of rows, which must equal the ambient dimension - of all cones and polyhedra.", - - PARA{}, "As a first example consider the following 2 dimensional cone in 3 space:", - - EXAMPLE { - " R = matrix {{1,2},{2,1},{0,0}}", - " C = posHull R" - }, - - PARA{}, "We can construct a full dimensional cone out of this one by adding a lineality - space for example:", - - EXAMPLE { - " LS = matrix {{0},{0},{1}}", - " C1 = posHull (R,LS)" - }, - - PARA{}, "The resulting cone is not pointed anymore, because it contains the subspace spanned - by (0,0,1). To get a full dimensional pointed cone we have to add another ray to C. For - this we can apply ",TT "posHull"," to a list containing ",TT "C"," and the new ray:", - - EXAMPLE { - " r = matrix {{0},{1},{2}}", - " C2 = posHull {C,r}" - }, - - PARA{}, "Another way would be, if we would have ",TT "r"," not as a ray but already as - a cone:", - - EXAMPLE { - " r = posHull r" - }, - - PARA{}, "In this case we can just take the positive hull of the two cones:", - - EXAMPLE { - " C3 = posHull(C,r)", - " C3 == C2" - } - - } - -document { - Key => {intersection, (intersection,Cone,Cone), (intersection,List), (intersection,Matrix), - (intersection,Matrix,Matrix), (intersection,Matrix,Matrix,Matrix,Matrix), (intersection,Polyhedron,Polyhedron), - (intersection,Cone,Polyhedron), (intersection,Polyhedron,Cone)}, - Headline => "computes the intersection of half-spaces, hyperplanes, cones, and polyhedra", - Usage => " P = intersection L \nC = intersection M \nC = intersection(M,N) \nP = intersection(M,v) \nP = intersection(M,v,N,w) \nC = intersection(C1,C2) \nP = intersection(P1,P2)", - Inputs => { - "L" => List => {"containing any of the inputs below"}, - "M" => Matrix => {"with entries in ", TO ZZ," or ", TO QQ}, - "N" => Matrix => {"with entries in ", TO ZZ," or ", TO QQ}, - "v" => Matrix => {"with only one column and entries in ", TO ZZ," or ", TO QQ}, - "w" => Matrix => {"with only one column and entries in ", TO ZZ," or ", TO QQ}, - "C1" => Cone, - "C2" => Cone, - "P1" => Polyhedron, - "P2" => Polyhedron - }, - Outputs => { - "P" => Polyhedron, - "C" => Cone - }, - - PARA{}, "When inserting any of the combination of matrices into ", - TT "intersection", ", it considers the given matrices as defining - inequalities and equalities. Thus, it either computes the polyhedron ", - TT "P = {p | M*p <= v and N*p = w }",". Therefore, ", TT "M", " and ", - TT "N", " must have the same number of columns, which will be the - dimension of the ambient space, and ", TT "M", " and ", TT "v", " as - well as ", TT "N", " and ", TT "w", " must have the same number of - rows respectively. If ", TT "N", " and ", TT "w", " are omitted then - the polyhedron is just given by the inequalities. If ", TT "v", " - and ", TT "w", " are omitted then they are considered to be 0 so - that the intersection is a cone and thus the output is of class Cone.", - - PARA{}, "If two polyhedra or two cones are inserted, then the - intersection of both arguments is computed if both arguments lie in - the same ambient space. If both arguments are cones then the output - is again a cone. Otherwise intersection returns a polyhedron.", - - PARA{}, "If ", TT "intersection", " is called for a list ", TT "L", ", - then the list may contain a combination of the following in any order.", - UL { - {"Inequalities, given by a sequence ", TT "(M,v)", " of matrices - over ", TO ZZ, " or ", TO QQ, " determining inequalities as above"}, - {"Equalities, given by a list ", TT "{N,w}", " of matrices - over ", TO ZZ, " or ", TO QQ, " determining equalities as above"}, - {TO Cone}, - {TO Polyhedron} - }, - - PARA{}, "Then ", TT "intersection", " computes the intersection of all - inserted objects, if they are in the same ambient space, i.e. all matrices - must have the same number of rows, which must equal the ambient dimension - of all cones and polyhedra.", - - PARA{}, "The first use of ",TT "intersection"," is to construct a cone:", - - EXAMPLE { - " M = matrix {{1,2,3},{2,3,1},{3,1,2}}", - " C = intersection M" - }, - - PARA{}, "This is the cone of all points that are positive on the rows of the - matrix ",TT "M",". If we add another row to this matrix and enter a condition - vector we get a polyhedron:", - - EXAMPLE { - " M = M || matrix {{-1,-1,-1}}", - " v = matrix {{1},{2},{3},{4}}", - " P = intersection(M,v)" - }, - - PARA{}, " This polyhedron, a tetrahedron, consists of all points ",TT "p"," such - that ",TT "M*p <= v",". If add a another pair of matrices, these conditions are - evaluated as equalities. Thus we get a polyhedron which is not of full dimension. - It is an intersection with an affine hyperplane.", - - EXAMPLE { - " N = matrix {{1,2,0}}", - " w = matrix {{2}}", - " Q = intersection (M,v,N,w)" - }, - - PARA{}, "If we have another polyhedron or cone, we can also intersect them with the others.", - - EXAMPLE { - " HC = intersection(matrix {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}},matrix {{1},{1},{1},{1},{1},{1}})", - " C1 = intersection(C,HC)", - " Q1 = intersection(P,HC)" - } - - } - -document { - Key => {makeFan, (makeFan,Cone), (makeFan,List)}, - Headline => "generates a Fan", - Usage => " F = makeFan C \nF = makeFan L", - Inputs => { - "C" => Cone, - "L" => List => {"with elements of class ", TO Cone, " or ", TO Fan} - }, - Outputs => { - "F" => Fan - }, - - PARA{}, " If ",TT "makeFan", " is applied to a ", TO Cone, " it generates - the ", TO Fan, " given by the Cone and all of its faces. If applied to - a ", TO List, " the list must only contain Cones and Fans in the same - ambient space. Then it adds the Cones in the List and the generating Cones - of the Fans in the List one by one to the Fan, checking each time if the - new Cone is compatible with the cones that have already been added, i.e. - that the intersection with each of them is a face of both Cones - (intersection condition).", - - PARA{}, "If one of the cones is in the wrong ambient space, there will be an - error and no fan will be returned. If the intersection condition fails, there - will also be an error. The pairs of incompatible cones can be accessed with the - function ",TO incompCones,".", - - EXAMPLE { - " C = posHull matrix {{1,-1},{0,-1}}", - " F = makeFan C", - " C1 = posHull matrix {{1,0},{0,1}};", - " C2 = posHull matrix {{0,-1},{1,-1}};", - " F = makeFan {C,C1,C2}" - } - - } - -document { - Key => {addCone, (addCone,Cone,Fan), (addCone,List,Fan), (addCone,Fan,Fan)}, - Headline => "adds cones to a Fan", - Usage => " F1 = addCone(C,F) \nF1 = addCone(L,F)", - Inputs => { - "C" => Cone, - "L" => List => {"with elements of class ", TO Cone, " or ", TO Fan}, - "F" => Fan - }, - Outputs => { - "F1" => Fan - }, - - PARA{}, "If ",TT "addCone", " is applied to a ", TO Cone, " and a ",TO Fan, " - it adds the Cone to the Fan if they are in the same ambient space, if the Cone is - compatible with every generating Cone of ",TT "F", ", but is not a face of one - of them. If one of the first two conditions fails, there will be an error and no fan - will be returned. The pairs of incompatible cones can be accessed with the - function ",TO incompCones,". If the last condition fails, then the cone is already in - the fan as a face of one of the cones, so it does not have to be added. The conditions - are checked in this order.", - - PARA{}, "If ",TT "addCone"," is applied to a ",TO List," and a ",TO Fan,", then - the function adds the list cone by cone and stops if one of the three conditions - fails for one of the cones. There is again an error for the first two conditions. The - pairs of incompatible cones can again be retrieved using ",TO incompCones,".", - - PARA{}, "If applied to a pair of fans it adds the generating cones of the first - fan to the second fan, again checking for the same conditions as above.", - - PARA{}, " As an example, we make a fan consisting of the following cone and - try to add an adjacent orthant.", - - EXAMPLE { - " C = posHull matrix {{1,0,0},{0,1,1},{0,0,1}};", - " F = makeFan C", - " C = posHull matrix {{-1,0,0},{0,1,0},{0,0,1}};", - " incompCones(C,F)" - }, - - PARA{}, "This shows that the two cones do not intersect in a common face, but - if we divide C into two parts, we get a fan.", - - EXAMPLE { - " C1 = intersection {C, (matrix {{0,1,-1}}, matrix {{0}})};", - " C2 = intersection {C, (matrix {{0,-1,1}}, matrix {{0}})};", - " F = addCone({C1,C2},F)" - } - - } - -document { - Key => {ambDim, (ambDim,Cone), (ambDim,Fan), (ambDim,Polyhedron)}, - Headline => "ambient dimension of a Polyhedron, Cone or Fan", - Usage => "d = ambDim P \nd = ambDim C \nd = ambDim F", - Inputs => { - "P" => Polyhedron, - "C" => Cone, - "F" => Fan - }, - Outputs => { - "d" => ZZ => {", the dimension of the ambient space"} - }, - - PARA{}, TT "ambDim", " returns the dimension of the ambient space - either of the ", TO Polyhedron," ",TT "P", ", of the ", TO Cone," ",TT "C", " - or the ", TO Fan," ",TT "F", ".", - - EXAMPLE { - " P = convexHull matrix{{1,0},{0,1}}", - " ambDim P", - } - } - -document { - Key => {cones, (cones,ZZ,Fan)}, - Headline => "computes all cones of a fan of a certain dimension", - Usage => " L = cones(d,F)", - Inputs => { - "d" => ZZ => {" between 0 and the dimension of the fan"}, - "F" => Fan - }, - Outputs => { - "L" => List - }, - - PARA{}, TT "cones", " computes the ", TO List, " of all Cones in ", - TT "F", " of dimension ", TT "d", ".", - - EXAMPLE { - " F = normalFan hypercube 3", - " L = cones(2,F)", - }, - - PARA{}, "To actually see the cones of the fan we can look at their - rays, for example:", - - EXAMPLE { - " apply(L,rays)" - } - - } - -document { - Key => {genCones, (genCones,Fan)}, - Headline => "displays the generating Cones of a Fan", - Usage => " L = genCones F", - Inputs => { - "F" => Fan - }, - Outputs => { - "L" => List - }, - - PARA{}, TT "genCones", " displays the ", TO List, " of generating cones - of the ", TO Fan, ", i.e. all Cones that are not a face of one - of the other cones. These are all of the same dimension if and only if - the Fan is pure (see: ", TO isPure,").", - - EXAMPLE { - " F = normalFan crossPolytope 3", - " L = genCones F", - " apply(L,rays)" - } - - } - -document { - Key => {halfspaces, (halfspaces,Cone), (halfspaces,Polyhedron)}, - Headline => "computes the defining half-spaces of a Cone or a Polyhedron", - Usage => " M = halfspaces C \n(M,v) = halfspaces P", - Inputs => { - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "M" => Matrix => {"with entries over ", TO QQ}, - "v" => Matrix => {"with entries over ", TO QQ, " and only one column"} - }, - - PARA{}, TT "halfspaces", " returns the defining affine half-spaces. For a - polyhedron ", TT "P", " the output is ", TT "(M,v)", ", where the source - of ", TT "M", " has the dimension of the ambient space of ", TT "P", " - and ", TT "v", " is a one column matrix in the target space - of ", TT "M", " such that ",TT "P = {p in H | M*p =< v}", " where - ", TT "H", " is the intersection of the defining affine hyperplanes.", - - PARA{}, " For a cone ", TT "C", " the output is the matrix", TT "M"," that is the - same matrix as before but ", TT "v", " is omitted since it is 0, - so ", TT "C = {c in H | M*c =< 0}", " and ", TT "H", " is the intersection - of the defining linear hyperplanes.", - - EXAMPLE { - " R = matrix {{1,1,2,2},{2,3,1,3},{3,2,3,1}};", - " V = matrix {{1,-1},{0,0},{0,0}};", - " C = posHull R", - " halfspaces C" - }, - - PARA{}, "Now we take this cone over a line and get a polyhedron.", - - EXAMPLE { - " P = convexHull(V,R)", - " halfspaces P" - } - - } - -document { - Key => {hyperplanes, (hyperplanes,Cone), (hyperplanes,Polyhedron)}, - Headline => "computes the defining hyperplanes of a Cone or a Polyhedron", - Usage => " N = hyperplanes C \n(N,w) = hyperplanes P", - Inputs => { - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "N" => Matrix => {"with entries over ", TO QQ}, - "w" => Matrix => {"with entries over ", TO QQ, " and only one column"} - }, - - PARA{}, TT "hyperplanes", " returns the defining affine hyperplanes for a - polyhedron ", TT "P", ". The output is ", TT "(N,w)", ", where the source - of ", TT "N", " has the dimension of the ambient space of ", TT "P", " - and ", TT "w", " is a one column matrix in the target space - of ", TT "N", " such that ",TT "P = {p in H | N*p = w}", " where - ", TT "H", " is the intersection of the defining affine half-spaces.", - - PARA{}, " For a cone ", TT "C", " the output is the matrix ", TT "N", ", that - is the same matrix as before but ", TT "w", " is omitted since it is 0, - so ", TT "C = {c in H | N*c = 0}", " and ", TT "H", " is the intersection - of the defining linear half-spaces.", - - EXAMPLE { - " P = stdSimplex 2", - " hyperplanes P", - " C = posHull matrix {{1,2,4},{2,3,5},{3,4,6}}", - " hyperplanes C" - } - - } - -document { - Key => {linSpace, (linSpace,Cone), (linSpace,Fan), (linSpace,Polyhedron)}, - Headline => "computes a basis of the lineality space", - Usage => " LS = linSpace C \nLS = linSpace F \nLS = linSpace P", - Inputs => { - "C" => Cone, - "F" => Fan, - "P" => Polyhedron - }, - Outputs => { - "LS" => Matrix - }, - - PARA{}, TT "linSpace", " returns a basis of the lineality space of the - input as the columns of the matrix ", TT "LS", ". The lineality space of a - Fan is the lineality space of any Cone of the Fan, since they all have the - same lineality space.", - - EXAMPLE { - " M = matrix {{1,1,1},{0,1,0},{-1,1,-1},{-1,-1,-1},{0,-1,0},{1,-1,1}};", - " v = matrix {{2},{1},{2},{2},{1},{2}};", - " P = intersection(M,v)", - " linSpace P", - " C = dualCone intersection M", - " linSpace C" - } - - } - -document { - Key => {rays, (rays,Cone), (rays,Fan), (rays,Polyhedron)}, - Headline => "displays all rays of a Cone, a Fan, or a Polyhedron", - Usage => " R = rays C \nR = rays F \nR = rays P", - Inputs => { - "C" => Cone, - "F" => Fan, - "P" => Polyhedron - }, - Outputs => { - "R" => Matrix - }, - - PARA{}, TT "rays", " returns the rays of the input as the columns of the - matrix ", TT "R", ".", - - EXAMPLE { - " P = convexHull(matrix {{1,-1,2,-2},{1,1,2,2}}, matrix {{0},{1}})", - " rays P", - " C = posHull P", - " rays C", - " F = normalFan P", - " rays F" - } - - } - -document { - Key => {vertices, (vertices,Polyhedron)}, - Headline => "displays the vertices of a Polyhedron", - Usage => " V = vertices P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "V" => Matrix - }, - - PARA{}, TT "vertices", " returns the vertices of the Polyhedron ", TT "P", " - as the columns of the Matrix ", TT "V",".", - - EXAMPLE { - " P = intersection(matrix{{1,-1},{0,-1},{-1,-1},{0,1}}, matrix{{0},{-1},{0},{1}})", - " vertices P" - } - - } - -document { - Key => {areCompatible, (areCompatible,Cone,Cone)}, - Headline => "checks if the intersection of two cones is a face of each", - Usage => " (b,C) = areCompatible(C1,C2)", - Inputs => { - "C1" => Cone, - "C2" => Cone - }, - Outputs => { - "b" => Boolean => {TO true, " if the intersection is a face of each cone, - and ", TO false, " otherwise."}, - "C" => Cone => {" the intersection of both Cones if they are compatible, otherwise - the empty polyhedron."} - }, - - PARA{}, TT "areCompatible", " is an extension of ", TO commonFace, " for Cones. It - also checks if the intersection ", TT "C", " of ", TT "C1", " and ", TT "C2", " is a - face of each and the answer is given by ", TT "b", ". Furthermore, the intersection - is given for further calculations if the two cones lie in the same ambient space. Otherwise, - the empty polyhedron in the ambient space of ",TT "C1"," is given.", - - PARA{}, "For example, consider the following three cones", - - EXAMPLE { - " C1 = posHull matrix {{1,0},{0,1}};", - " C2 = posHull matrix {{1,-1},{0,-1}};", - " C3 = posHull matrix {{1,-1},{2,-1}};", - }, - - PARA{}, "These might form a fan, but if we check if they are compatible, we see they - are not:", - - EXAMPLE { - " areCompatible(C1,C2)", - " areCompatible(C2,C3)", - " areCompatible(C3,C1)", - } - - } - -document { - Key => {commonFace, (commonFace,Cone,Cone), (commonFace,Polyhedron,Polyhedron), - (commonFace,Cone,Fan), (commonFace,Fan,Cone), (commonFace,Fan,Fan)}, - Headline => "checks if the intersection is a face of both Cones or Polyhedra, or of cones with fans", - Usage => " b = commonFace(C1,C2) \nb = commonFace(P1,P2) \nb = commonFace(X,F) \nb = commonface(F,X)", - Inputs => { - "C1" => Cone, - "C2" => Cone, - "P1" => Polyhedron, - "P2" => Polyhedron, - "F" => Fan, - "X" => {TO Cone," or ",TO Fan} - }, - Outputs => { - "b" => Boolean => {TO true, " if the intersection is a face both, - and ", TO false, " otherwise."} - }, - - PARA{}, TT "commonFace", " checks if the intersection of ", TT "C1", " - and ", TT "C2", " or the intersection of ", TT "P1", " and ", TT "P2", " is - a face of both. If it is applied to a pair of a cone ",TT "C"," and a fan ",TT "F"," then - it checks if the intersection of ",TT "C"," with every generating cone of ",TT "F"," is - a face of each. For two fans it checks this condition for every pair of generating cones. ", - - PARA{}, "For example, consider the following three cones:", - - EXAMPLE { - " C1 = posHull matrix {{1,0},{0,1}};", - " C2 = posHull matrix {{1,-1},{0,-1}};", - " C3 = posHull matrix {{1,-1},{2,-1}};", - }, - - PARA{}, "for each pair of two of them we can check if their intersection is a common face:", - - EXAMPLE { - " commonFace(C1,C2)", - " commonFace(C2,C3)", - " commonFace(C3,C1)", - } - - } - -document { - Key => {contains, (contains,Cone,Cone), (contains,Cone,Matrix), (contains,Cone,Polyhedron), - (contains,Fan,Cone), (contains,List,Cone), (contains,List,Polyhedron), (contains,Polyhedron,Cone), - (contains,Polyhedron,Matrix), (contains,Polyhedron,Polyhedron)}, - Headline => "checks if the first argument contains the second argument", - Usage => " b = contains(C,X) \nb = contains(P,X) \nb = contains(F,C) \nb = contains(L,C) \nb = contains(L,P)", - Inputs => { - "C" => Cone, - "P" => Polyhedron, - "F" => Fan, - "L" => List, - "X" => {"either a ", TO Cone,", a ", TO Polyhedron,", or a ", TO Matrix," with only one - column giving a point."} - }, - Outputs => { - "b" => Boolean => { TO true, " if the first argument contains the second argument, ", - TO false, " otherwise."} - }, - - PARA{}, TT "contains", " determines if the first argument contains the second argument. - Both arguments have to lie in the same ambient space. When the first argument is a Cone or - Polyhedron, it tests if the equations of the first argument are satisfied by the generating - points/rays of the second argument.", - - PARA{}, "For example, we can check if the 3 dimensional crosspolytope contains the hypercube - or the other way around:", - - EXAMPLE { - " P = hypercube 3", - " Q = crossPolytope 3", - " contains(Q,P)", - " contains(P,Q)" - }, - - PARA{}, "We can also check if the hypercube lies in the positive orthant.", - - EXAMPLE { - " C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}};", - " contains(C,P)", - " P = affineImage(P,matrix{{1},{1},{1}})", - " contains(C,P)" - } - - } - -document { - Key => {isCompact, (isCompact,Polyhedron)}, - Headline => "checks compactness of a Polyhedron", - Usage => " b = isCompact P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "b" => Boolean => { TO true, " if the ", TO Polyhedron, " is compact, ", TO false, " otherwise"} - }, - - PARA{}, TT "isCompact", " tests whether ", TT "P"," is compact, i.e. a polytope, by checking if the - rays and lineality space matrices are 0.", - - EXAMPLE { - " P = intersection(matrix{{1,1,1},{0,1,0},{-1,-1,-1},{-1,-1,-1},{0,-1,0},{1,-1,1}},matrix{{2},{1},{2},{2},{1},{2}})", - " isCompact P" - } - - } - -document { - Key => {isComplete, (isComplete,Fan)}, - Headline => "checks completeness of a Fan", - Usage => " b = isComplete F", - Inputs => { - "F" => Fan - }, - Outputs => { - "b" => Boolean => { TO true, " if the ", TO Fan, " is complete, ", TO false, " otherwise"} - }, - - PARA{}, TT "isComplete"," just calls an entry in the hash table of the Fan. The check for completeness - is done while generating the fan. Whenever a full dimensional Cone is added (see ", TO makeFan," - or ", TO addCone,") the set of faces of codimension 1 that appear only in one full dimensional Cone - is updated. The Fan is then complete if and only if this set is empty and there is at least one - full dimensional Cone.", - - EXAMPLE { - " C1 = posHull matrix {{1,0},{0,1}};", - " C2 = posHull matrix {{1,-1},{0,-2}};", - " C3 = posHull matrix {{0,-2},{1,-1}};", - " F = makeFan {C1,C2,C3}", - " isComplete F" - }, - - PARA{}, "Hence the fan above is not complete, but we can add the missing cone:", - - EXAMPLE { - " C4 = posHull matrix {{-1,-2},{-2,-1}};", - " F = addCone(C4,F)", - " isComplete F" - } - - } - -document { - Key => {isEmpty, (isEmpty,Polyhedron)}, - Headline => "checks if a Polyhedron is empty", - Usage => " b = isEmpty P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "b" => Boolean => { TO true, " if the ", TO Polyhedron, " is empty, ", TO false, " otherwise"} - }, - - PARA{}, "The polyhedron is empty if the dimension is -1.", - - EXAMPLE { - " P = intersection(matrix{{1,0},{0,1},{-1,-1}},matrix{{-1},{1},{-1}})", - " isEmpty P" - } - - } - -document { - Key => {isFace, (isFace,Cone,Cone), (isFace,Polyhedron,Polyhedron)}, - Headline => "tests if the first argument is a face of the second", - Usage => "b = isFace(X,Y)", - Inputs => { - "X" => Cone => {" or ", TO Polyhedron}, - "Y" => {"an element of the same class as ", TT "X"} - }, - Outputs => { - "b" => Boolean => { TO true, " if ", TT "X", " is a face of ",TT "Y",", false otherwise"} - }, - - PARA{}, "Both arguments must lie in the same ambient space. Then ", TT "isFace", " computes all - faces of ",TT "Y"," with the dimension of ",TT "X"," and checks if one of them is ",TT "X",".", - - EXAMPLE { - " P = hypercube 3", - " Q = convexHull matrix{{1,1,1},{1,1,-1},{1,-1,1}}", - " isFace(Q,P)" - }, - - PARA{}, "Thus, ",TT "Q"," is not a face of ",TT "P",", but we can extend it to a face.", - - EXAMPLE { - " v = matrix{{1},{-1},{-1}};", - " Q = convexHull{Q,v}", - " isFace(Q,P)" - } - - } - -document { - Key => (isNormal,Polyhedron), - Headline => "checks if a polytope is normal in the ambient lattice", - Usage => "b = isNormal P", - Inputs => { - "P" => Polyhedron => {"which must be compact"} - }, - Outputs => { - "b" => Boolean => {"true if P is normal in the ambient lattice"} - }, - - PARA{}, TT "isNormal"," can only be applied to polytopes, i.e. compact polyhedra. It - embeds the polytope on height 1 in a space of dimension plus 1 and takes the Cone over - this polytope. Then it checks if all elements of the Hilbert basis lie in height 1.", - - EXAMPLE { - " P = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0},{1,1,3}}", - " isNormal P" - } - - } - -document { - Key => {isPointed, (isPointed,Cone), (isPointed,Fan)}, - Headline => "checks if a Cone or Fan is pointed", - Usage => "b = isPointed C \nb = isPointed F", - Inputs => { - "C" => Cone, - "F" => Fan - }, - Outputs => { - "b" => Boolean => {TO true, " if the ",TO Cone," or the ",TO Fan," is pointed, false otherwise"} - }, - - PARA{}, "Tests if a Cone is pointed, i.e. the lineality space is 0. A Fan is pointed if one of its - Cones is pointed. This is equivalent to all Cones being pointed.", - - EXAMPLE { - " C = intersection(matrix{{1,1,-1},{-1,-1,-1}})", - " isPointed C", - " C = intersection{C,(matrix{{1,-1,-1}},0)}", - " isPointed C" - } - - } - -document { - Key => {isProjective, (isProjective,Fan)}, - Headline => "checks if a Fan is projective", - Usage => "b = isProjective F", - Inputs => { - "F" => Fan - }, - Outputs => { - "P" => Polyhedron => {TO emptyPolyhedron," if the ", TO Fan," is not projective and a ", TO Polyhedron," such - that 'F' is its normal fan if 'F' is projective"} - }, - - PARA{}, "If ",TT "F"," is projective, then there exists a polyhedron ",TT "P"," such that ",TT "F"," - is the normalFan of ",TT "P",". This means every codimension 1 cone of the Fan corresponds exactly to - an edge of the polytope. So consider ", TO QQ," to the number of all edges. This can be considered as the - space of all edge lengths. If we take arbitrary lengths now for every edge we do not get a polytope. But - every codimension 2 cone of the fan corresponds to a 2 dimensional face of the polytope and if the edges - belonging to this face add up to 0 zero, they form in fact a 2 dimensional face. This gives linear - equations on the space of edge lengths and if we intersect these equations with the positive orthant in - the space of edge lengths we get a Cone. Thus, there exists such a polytope if and only if there is a - vector in this cone with strictly positive entries, since every edge has to appear in the polytope.", - - PARA{}, "Note that the function first checks if the fan is complete.", - - EXAMPLE { - " C1 = posHull matrix {{1,0},{0,1}};", - " C2 = posHull matrix {{1,-1},{0,-2}};", - " C3 = posHull matrix {{0,-2},{1,-1}};", - " C4 = posHull matrix {{-1,-2},{-2,-1}};", - " F = makeFan{C1,C2,C3,C4}", - " isProjective F" - } - - } - -document { - Key => {isPure, (isPure,Fan)}, - Headline => "checks if a Fan is of pure dimension", - Usage => " b = isPure F", - Inputs => { - "F" => Fan - }, - Outputs => { - "b" => {TO true," if the ", TO Fan," is of pure dimension, ",TO false," otherwise"} - }, - - PARA{}, TT "isPure", " tests if the ", TO Fan," is pure by checking if the first and the last entry in - the list of generating Cones are of the same dimension.", - - PARA{}, "Let us construct a fan consisting of the positive orthant and the ray ",TT "v"," that is the - negative sum of the canonical basis, which is obviously not pure:", - - EXAMPLE { - " C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}", - " v = posHull matrix {{-1},{-1},{-1}}", - " F = makeFan {C,v}", - " isPure F", - }, - - PARA{}, "But we can make a pure fan if we choose any two dimensional face of the positive - orthant and take the cone generated by this face and ",TT "v"," and add it to the cone:", - - EXAMPLE { - " C1 = posHull{(faces(1,C))#0,v}", - " F = addCone(C1,F)", - " isPure F" - } - - } - -document { - Key => {isSmooth, (isSmooth,Cone), (isSmooth,Fan)}, - Headline => "checks if a Cone or Fan is smooth", - Usage => " b = isSmooth C \nb = isSmooth F", - Inputs => { - "C" => Cone - }, - Outputs => { - "b" => {TO true," if the ", TO Cone,"/",TO Fan," is smooth, ",TO false," otherwise"} - }, - - PARA{}, TT "isSmooth"," checks for a ",TO Cone," if the rays are a subset of a basis of the - lattice. For a ",TO Fan," it checks smoothness for every ",TO Cone,".", - - EXAMPLE { - " C = posHull matrix {{1,2,3},{3,1,2},{2,3,1}}", - " isSmooth C", - " F = hirzebruch 3", - " isSmooth F" - } - - } - -document { - Key => {faces, (faces,ZZ,Cone), (faces,ZZ,Polyhedron)}, - Headline => "computes all faces of a certain codimension of a Cone or Polyhedron", - Usage => " L = faces(k,C) \nL = faces(k,P)", - Inputs => { - "k" => ZZ, - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "L" => List => {"containing the faces of codimension ",TT "k"} - }, - - PARA{}, TT "faces"," computes the faces of codimension ",TT "k"," of the given ",TO Cone," - or ",TO Polyhedron,", where ",TT "k"," must be between 0 and the dimension of the second - argument. The faces will be of the same class as the original convex object.", - - PARA{}, "For example, we can look at the edges of the cyclicPolytope with 5 vertices in 3 space", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " L = faces(2,P)" - }, - - PARA{}, "Since this is only a list of polyhedra we look at their vertices:", - - EXAMPLE { - " apply(L,vertices)" - } - } - -document { - Key => {fVector, (fVector,Cone), (fVector,Polyhedron)}, - Headline => "computes the f-vector of a Cone or Polyhedron", - Usage => " f = fVector C \nf = fVector P", - Inputs => { - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "L" => List => {"containing the number of faces for each codimension"} - }, - - PARA{}, "The ",TT "i","-th entry of the f-vector of ",TT "P"," is the number of dimension ", - TT "i","-1 faces of ",TT "P",", so it starts with the number vertices, has - dim(",TT "P",")+1 entries, and the last entry is 1 for ",TT "P"," itself. It is the same for - a Cone ",TT "C",".", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " fVector P" - } - - } - -document { - Key => {hilbertBasis, (hilbertBasis,Cone)}, - Headline => "computes the Hilbert basis of a Cone", - Usage => " HB = hilbertBasis C", - Inputs => { - "C" => Cone - }, - Outputs => { - "L" => List => {"containing the elements of the Hilbert basis"} - }, - - PARA{}, "The Hilbert basis of the cone ",TT "C"," is computed by the - Project-and-Lift-algorithm by Raymond Hemmecke (see below). It computes a Hilbert basis of - the cone modulo the lineality space, so it returns the list of one column matrices that give - the Hilbert basis of the Cone if one adds the basis of the lineality space and its negative. - For the Project-and-Lift-algorithm see: ", - - PARA{}, HREF("http://www.hemmecke.de/raymond/", "Raymond Hemmecke's"), " ", EM "On the - computation of Hilbert bases of cones", ", in A. M. Cohen, X.-S. Gao, and N. Takayama, - editors, Mathematical Software, ICMS 2002, pages 307317. World Scientific, 2002.", - - EXAMPLE { - " C = posHull matrix {{1,2},{2,1}}", - " hilbertBasis C" - } - - } - -document { - Key => {incompCones, (incompCones,List), (incompCones,Cone,Fan), (incompCones,Fan,Cone), (incompCones,Fan,Fan)}, - Headline => "returns the pairs of incompatible cones", - Usage => " Lpairs = incompCones L \nLpairs = incompCones(X,F) \nLpairs = incompCones(F,X)", - Inputs => { - "L" => List, - "F" => Fan, - "X" => {TO Cone," or ",TO Fan,} - }, - Outputs => { - "Lpairs" => List - }, - - PARA{}, "If ",TT "incompCones"," is applied to a list of cones and fans, then it returns the pairs of elements - whose intersection is not a face of each. For a cone ",TT "C"," and a fan ",TT "F"," in the list this means there - is at least one generating cone of ",TT "F"," whose intersection with ",TT "C"," is not a face of each. For two - fans in the list this means there is at least one generating cone each such that their intersection is not a face - of each. If applied to a pair consisting of a cone and a fan or two fans, then it returns the pairs of cones that - do not share a common face.", - - EXAMPLE { - " C1 = posHull matrix{{1,0},{1,1}};", - " C2 = posHull matrix{{1,0},{0,-1}};", - " C3 = posHull matrix{{-1,0},{0,1}};", - " C4 = posHull matrix{{1,1},{0,1}};", - " C5 = posHull matrix {{1,2},{2,1}};", - " L = {C1,C2,C3,C4,C5};", - " Lpairs = incompCones L", - " Lpairs == {(C1,C4),(C1,C5)}", - } - - } - -document { - Key => {inInterior, (inInterior,Matrix,Cone), (inInterior,Matrix,Polyhedron)}, - Headline => "checks if a point lies in the relative interior of a Cone/Polyhedron", - Usage => " b = inInterior(p,C) \nb = inInterior(p,P)", - Inputs => { - "p" => Matrix => {" over ",TO ZZ," or ",TO QQ," with only one column representing a point"}, - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "b" => Boolean => {TO true, " if ",TT "p"," lies in the relative interior of the - Cone/Polyhedron, ", TO false," otherwise"} - }, - - PARA{}, TT "inInterior", " checks if the smallest face of the ",TO Cone," or - the ",TO Polyhedron," containing ",TT "p"," is the ",TO Cone," or - the ",TO Polyhedron," itself. For this the number of rows of ",TT "p"," must - equal the ambient dimension of the second argument.", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " p = matrix{{2},{4},{8}}", - " q = matrix{{2},{6},{20}}", - " inInterior(p,P)", - " inInterior(q,P)" - } - - } - -document { - Key => {interiorPoint, (interiorPoint,Polyhedron)}, - Headline => "computes a point in the relative interior of the Polyhedron", - Usage => " p = interiorPoint P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "p" => Matrix => {" over ",TO QQ," with only one column representing a point"} - }, - - PARA{}, TT "interiorPoint", " takes the vertices of the ",TO Polyhedron," and computes the sum - multiplied by ",TT "1/n",", where ",TT "n"," is the number of vertices.", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " interiorPoint P" - } - - } - -document { - Key => {interiorVector, (interiorVector,Cone)}, - Headline => "computes a vector in the relative interior of a Cone", - Usage => " p = interiorVector C", - Inputs => { - "C" => Cone - }, - Outputs => { - "p" => Matrix => {" over ",TO QQ," with only one column representing a vector"} - }, - - PARA{}, TT "interiorVector", " takes the rays of the ",TO Cone,", computes the sum and - divides by the gcd to get a primitive vector.", - - EXAMPLE { - " P = cyclicPolytope(3,4)", - " C = posHull P", - " interiorVector C" - } - - } - -document { - Key => {latticePoints, (latticePoints,Polyhedron)}, - Headline => "computes the lattice points of a polytope", - Usage => " L = latticePoints P", - Inputs => { - "P" => Polyhedron => {"which must be compact"} - }, - Outputs => { - "L" => List => {"containing the lattice points as matrices over ",TO ZZ," with only - one column"} - }, - - PARA{}, TT "latticePoints"," can only be applied to polytopes, i.e. compact polyhedra. It - embeds the polytope on height 1 in a space of dimension plus 1 and takes the Cone over - this polytope. Then it projects the elements of height 1 of the Hilbert basis back again.", - - EXAMPLE { - " P = crossPolytope 3", - " latticePoints P", - " Q = cyclicPolytope(2,4)", - " latticePoints Q" - } - - } - -document { - Key => {maxFace, (maxFace,Matrix,Polyhedron), (maxFace,Matrix,Cone)}, - Headline => "computes the face of a Polyhedron or Cone where a weight attains its maximum", - Usage => " F = maxFace(w,P) \nF = maxFace(w,C)", - Inputs => { - "w" => Matrix => {" over ",TO ZZ," or ",TO QQ," with only one column representing a - weight vector"}, - "P" => Polyhedron, - "C" => Cone - }, - Outputs => { - "F" => {"Depending on the input, a Cone or a Polyhedron, the face where ",TT "w"," attains - its maximum"} - }, - - PARA{}, TT "maxFace"," computes the face of the given Polyhedron ",TT "P"," or Cone ",TT "C"," - where ",TT "w"," attains its maximum.", - - EXAMPLE { - " P = crossPolytope 3", - " w = matrix {{1},{-1},{0}}", - " F = maxFace(w,P)", - " vertices F" - } - } - - -document { - Key => {minFace, (minFace,Matrix,Polyhedron), (minFace,Matrix,Cone)}, - Headline => "computes the face of a Polyhedron or Cone where a weight attains its minimum", - Usage => " F = minFace(w,P) \nF = minFace(w,C)", - Inputs => { - "w" => Matrix => {" over ",TO ZZ," or ",TO QQ," with only one column representing a - weight vector"}, - "P" => Polyhedron, - "C" => Cone - }, - Outputs => { - "F" => {"Depending on the input, a Cone or a Polyhedron, the face where ",TT "w"," attains - its minimum"} - }, - - PARA{}, TT "minFace"," computes the face of the given Polyhedron ",TT "P"," or Cone ",TT "C"," - where ",TT "w"," attains its minimum.", - - EXAMPLE { - " P = hypercube 3", - " w = matrix {{1},{2},{0}}", - " F = minFace(w,P)", - " vertices F" - } - } - - -document { - Key => {minkSummandCone, (minkSummandCone,Polyhedron)}, - Headline => "computes the Cone of all Minkowski summands and the minimal decompositions", - Usage => " (C,L,M) = minkSummandCone P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "C" => Cone, - "L" => List => {" containing Polyhedra"}, - "M" => Matrix - }, - - PARA{}, "For the Minkowski summand cone one takes ",TO QQ,"^d where d is the number - of edges of the input polyhedron ",TT "P",". Every Minkowski summand of ",TT "P"," has - only edges that are edges of ",TT "P",", so it can be constructed by rescaling every - edge of ",TT "P",", i.e. is represented by a point in ",TO QQ,"^d. But not every point - in ",TO QQ,"^d gives a polyhedron via this method. This is the case if on the one - hand the point lies in the positive orthant and on the other hand for every compact two - dimensional face of ",TT "P"," the rescaled edges of such a face give a two dimensional - polytope, i.e. the sum of the ordered rescaled edge directions is zero. Therefore, every - compact two dimensional face of ",TT "P"," gives a set of linear equalities on a part of - the variables in ",TO QQ,"^d. The Minkowski Summand Cone ",TT "C"," is the intersection - of the positive orthant with these equations. Thus, every point in ",TT "C"," corresponds - to a Minkowski summand (probably after rescaling). The corresponding polyhedron to every - minimal generator of ",TT "C"," is saved in the hash table ",TT "L",". Finally, all possible - minimal decompositions of ",TT "P"," are saved as columns in the matrix ",TT "M",".", - - PARA{}, "For example, consider the Minkowski summand cone of the hexagon.", - - EXAMPLE { - " P = convexHull matrix{{2,1,-1,-2,-1,1},{0,1,1,0,-1,-1}}", - " (C,L,M) = minkSummandCone P" - }, - - PARA{}, "Thus, we see that the minimal Minkowski summands of the hexagon are two triangles - and three lines and that there are two minimal decompositions, i.e. the hexagon is the sum - of the two triangles or the three lines:", - - EXAMPLE { - " rays C", - " apply(values L,vertices)", - " M" - } - - } - -document { - Key => {proximum, (proximum,Matrix,Polyhedron), (proximum,Matrix,Cone)}, - Headline => "computes the proximum of the Polyhedron/Cone to a point in euclidian metric", - Usage => " q = proximum(p,P) \nq = proximum(p,C)", - Inputs => { - "p" => Matrix => {" over ",TO ZZ," or ",TO QQ," with only one column representing a point"}, - "P" => Polyhedron, - "C" => Cone - }, - Outputs => { - "q" => Matrix => {" over ",TO QQ," with only one column representing the closest point"} - }, - - PARA{}, "For a point ",TT "p"," and a Polyhedron ",TT "P"," or a Cone ",TT "C",", ",TT "proximum"," - computes the point in ",TT "P"," or ",TT "C"," with minimal euclidian distance to ",TT "p",".", - - EXAMPLE { - " P = crossPolytope 3", - " p = matrix {{1},{2},{3}}", - " q = proximum(p,P)" - } - - } - -document { - Key => {skeleton, (skeleton,ZZ,Fan)}, - Headline => "computes the k-skeleton of a Fan", - Usage => " F1 = skeleton(k,F)", - Inputs => { - "k" => ZZ, - "F" => Fan - }, - Outputs => { - "F1" => Fan - }, - - PARA{}, "For an integer ",TT "k"," between 0 and the dimension of ",TT "F",", - ",TT "skeleton"," computes the ",TT "k","-skeleton of the ",TO Fan," ",TT "F",", - i.e. the ",TO Fan," ",TT "F1"," generated by all cones of dimension - ",TT "k"," in ",TT "F",".", - - PARA{}, "For example, we can look at the 2-skeleton of the fan of projective - 3-space:", - - EXAMPLE { - " P = convexHull matrix{{1,0,0,0},{0,1,0,0},{0,0,1,0}}", - " F = normalFan P", - " F1 = skeleton(2,F)", - " apply(genCones F1,rays)" - } - - } - -document { - Key => {smallestFace, (smallestFace,Matrix,Cone), (smallestFace,Matrix,Polyhedron)}, - Headline => "determines the smallest face of the Cone/Polyhedron containing a point", - Usage => " C1 = smallestFace(p,C) \nP1 = smallestFace(p,P)", - Inputs => { - "p" => Matrix => {"over ",TO ZZ," or ",TO QQ," with only one column representing a point"}, - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "C1" => Cone => {" or"}, - "P1" => Polyhedron - }, - - PARA{}, TT "p"," is considered to be a point in the ambient space of the second argument, so - the number of rows of ",TT "p"," must equal the dimension of the ambient space of the - second argument. The function computes the smallest face of the second argument that - contains ",TT "p",". If the second argument is a ",TO Polyhedron," the output is a - ",TO Polyhedron," and if it is a ",TO Cone," the output is a ",TO Cone,". In both cases, - if the point is not contained in the second argument then the output is the empty - polyhedron.", - - EXAMPLE { - " P = hypercube 3", - " p = matrix {{1},{0},{0}}", - " smallestFace(p,P)" - } - - } - -document { - Key => {smoothSubfan, (smoothSubfan,Fan)}, - Headline => "computes the subfan of all smooth cones", - Usage => " F1 = smoothSubfan F", - Inputs => { - "F" => Fan - }, - Outputs => { - "F1" => Fan - }, - - PARA{}, " For a given ",TO Fan," ",TT "F"," the function computes the subfan ",TT "F1"," of - all smooth cones.", - - PARA{}, "Let's consider the fan consisting of the following three dimensional cone and all - of its faces:", - - EXAMPLE { - " C = posHull matrix {{1,-1,0},{1,1,0},{1,1,1}}", - " F = makeFan C" - }, - - PARA{}, "This cone is not smooth, therefore also the fan is not. But if we remove the interior and one - of the two dimensional faces the resulting subfan is smooth.", - - EXAMPLE { - " F1 = smoothSubfan F", - " apply(genCones F1, rays)" - } - - } - -document { - Key => {tailCone, (tailCone,Polyhedron)}, - Headline => "computes the tail/recession cone of a polyhedron", - Usage => " C = tailCone P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "C" => Cone - }, - - PARA{}, "Every polyhedron ",TT "P"," can be uniquely decomposed into the sum of a - polytope and a cone, the tail or recession cone of ",TT "P",". Thus, it is the cone - generated by the non-compact part, i.e. the rays and the lineality space - of ",TT "P",". If ",TT "P"," is a polytope then the tail cone is the origin in the - ambient space of ",TT "P",".", - - EXAMPLE { - " P = intersection(matrix{{-1,0},{1,0},{0,-1},{-1,-1},{1,-1}},matrix{{2},{2},{-1},{0},{0}}) ", - " C = tailCone P", - " rays C" - } - - } - -document { - Key => {triangulate, (triangulate,Polyhedron)}, - Headline => "computes a triangulation of a polytope", - Usage => " L = triangulate P", - Inputs => { - "P" => Polyhedron => {", which must be compact"} - }, - Outputs => { - "L" => List => {" containing the simplices of the triangulation"} - }, - - PARA{}, TT "triangulate"," computes the triangulation of the polyhedron ",TT "P",", if it is compact, - i.e. a polytope, recursively. For this, it takes all facets and checks if they are simplices. If so, then - it takes the convex hull of these with the weighted centre of the polytope (the sum of the vertices divided - by the number of vertices). For those that are not simplices it takes all their facets and does the same - for these.", - - EXAMPLE { - " P = hypercube 2", - " triangulate P" - } - - } - -document { - Key => {volume, (volume,Polyhedron)}, - Headline => "computes the volume of a polytope", - Usage => " v = volume P", - Inputs => { - "P" => Polyhedron => {", which must be compact"} - }, - Outputs => { - "v" => QQ - }, - - PARA{}, TT "volume"," computes the volume of a polytope. To do this, it triangulates the polytope first. The volume - of a simplex is |det(v_1-v_0,..,v_n-v_0)|/n!, where v_0,..,v_n are the vertices of the simplex.", - - EXAMPLE { - " P = crossPolytope 3", - " volume P" - } - - } - -document { - Key => {vertexEdgeMatrix, (vertexEdgeMatrix,Polyhedron)}, - Headline => "computes the vertex-edge-relations matrix", - Usage => " M = vertexEdgeMatrix P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "M" => Matrix - }, - - PARA{}, TT "vertexEdgeMatrix"," computes the matrix ",TT "M"," where the columns are indexed - by the edges and the rows are indexed by the vertices of ",TT "P"," and has 1 as an entry - if the corresponding edge contains this vertex and 0 otherwise.", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " vertexEdgeMatrix P" - } - - } - -document { - Key => {vertexFacetMatrix, (vertexFacetMatrix,Polyhedron)}, - Headline => "computes the vertex-facet-relations matrix", - Usage => " M = vertexFacetMatrix P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "M" => Matrix - }, - - PARA{}, TT "vertexFacetMatrix"," computes the matrix ",TT "M"," where the columns are indexed - by the facets and the rows are indexed by the vertices of ",TT "P"," and has 1 as an entry - if the corresponding facet contains this vertex and 0 otherwise.", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " vertexFacetMatrix P" - } - - } - -document { - Key => {affineHull, (affineHull,Polyhedron)}, - Headline => "computes the affine hull of a polyhedron", - Usage => " Q = affineHull P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the affine hull of a polyhedron. This is the affine subspace with the same - dimension as the polyhedron, containing the polyhedron.", - - EXAMPLE { - " P = stdSimplex 3", - " Q = affineHull P", - " linSpace Q" - } - - } - -document { - Key => affineImage, - Headline => "computes the affine image of a cone or polyhedron" - } - -document { - Key => {(affineImage,Matrix,Cone,Matrix), (affineImage,Matrix,Cone), - (affineImage,Cone,Matrix)}, - Headline => "computes the affine image of a cone", - Usage => " C1 = affineImage(A,C,b) \nC1 = affineImage(A,C) \nC1 = affineImage(C,b)", - Inputs => { - "A" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ}, - "C" => Cone, - "b" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ," and only one column representing a vector"} - }, - Outputs => { - "C1" => {" of class ",TO Cone," or ",TO Polyhedron} - }, - - PARA{}, TT "A"," must be a matrix from the ambient space of the cone ",TT "C"," to some - other target space and ",TT "b"," must be a vector in that target space, i.e. the number of - columns of ",TT "A"," must equal the ambient dimension of ",TT "C"," and ",TT "A"," and ",TT "b"," - must have the same number of rows. Then ",TT "affineImage"," computes the - polyhedron ",TT "{(A*c)+b | c in C}"," and the cone ",TT "{A*c | c in C}"," if ",TT "b"," is 0 or omitted. - If ",TT "A"," is omitted then it is set to identity.", - - PARA{}, "For example, consider the following three dimensional cone.", - - EXAMPLE { - " C = posHull matrix {{1,2,3},{3,1,2},{2,3,1}}", - }, - - PARA{}, "This Cone can be mapped to the positive orthant:", - - EXAMPLE { - " A = matrix {{-5,7,1},{1,-5,7},{7,1,-5}}", - " C1 = affineImage(A,C)", - " rays C1", - } - - } - -document { - Key => {(affineImage,Matrix,Polyhedron,Matrix), (affineImage,Matrix,Polyhedron), - (affineImage,Polyhedron,Matrix)}, - Headline => "computes the affine image of a polyhedron", - Usage => " P1 = affineImage(A,P,v) \nP1 = affineImage(A,P) \nP1 = affineImage(P,v)", - Inputs => { - "A" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ}, - "P" => Polyhedron, - "v" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ," and only one column representing a vector"} - }, - Outputs => { - "P1" => Polyhedron - }, - - PARA{}, TT "A"," must be a matrix from the ambient space of the polyhedron ",TT "P"," to some - other target space and ",TT "v"," must be a vector in that target space, i.e. the number of - columns of ",TT "A"," must equal the ambient dimension of ",TT "P"," and ",TT "A"," and ",TT "v"," - must have the same number of rows. Then ",TT "affineImage"," computes the - polyhedron ",TT "{(A*p)+v | p in P}"," where ",TT "v"," is set to 0 if omitted and ",TT "A"," is the - identity if omitted.", - - PARA{}, "For example, consider the following two dimensional polytope:", - - EXAMPLE { - " P = convexHull matrix {{-2,0,2,4},{-8,-2,2,8}}", - }, - - PARA{}, "This polytope is the affine image of the square:", - - EXAMPLE { - " A = matrix {{-5,2},{3,-1}}", - " v = matrix {{5},{-3}}", - " Q = affineImage(A,P,v)", - " vertices Q", - } - - } - -document { - Key => affinePreimage, - Headline => "computes the affine preimage of a cone or polyhedron" - } - -document { - Key => {(affinePreimage,Matrix,Cone,Matrix), (affinePreimage,Matrix,Cone), - (affinePreimage,Cone,Matrix)}, - Headline => "computes the affine preimage of a cone", - Usage => " C1 = affinePreimage(A,C,b) \nC1 = affinePreimage(A,C) \nC1 = affinePreimage(C,b)", - Inputs => { - "A" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ}, - "C" => Cone, - "b" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ," and only one column representing a vector"} - }, - Outputs => { - "C1" => {" of class ",TO Cone," or ",TO Polyhedron} - }, - - PARA{}, TT "A"," must be a matrix from some source space to the ambient space of ",TT "C"," and ",TT "b"," must be - a vector in that ambient space, i.e. the number of rows of ",TT "A"," must equal the ambient dimension of ",TT "C"," - and the number of rows of ",TT "b",". ",TT "affinePreimage"," then computes the - polyhedron ",TT "{q | (A*q)+b in C}"," or the cone ",TT "{q | (A*q) in C}"," if ",TT "b"," is 0 or omitted. - If ",TT "A"," is omitted then it is set to identity.", - - PARA{}, "For example, consider the following three dimensional cone:", - - EXAMPLE { - " C = posHull matrix {{1,2,3},{3,1,2},{2,3,1}}", - }, - - PARA{}, "We can look at its preimage under the following map:", - - EXAMPLE { - " A = matrix {{-5,7,1},{1,-5,7},{7,1,-5}}", - " C1 = affinePreimage(A,C)", - " rays C1", - } - - } - -document { - Key => {(affinePreimage,Matrix,Polyhedron,Matrix), (affinePreimage,Matrix,Polyhedron), - (affinePreimage,Polyhedron,Matrix)}, - Headline => "computes the affine preimage of a polyhedron", - Usage => " P1 = affinePreimage(A,P,v) \nP1 = affinePreimage(A,P) \nP1 = affinePreimage(P,v)", - Inputs => { - "A" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ}, - "P" => Polyhedron, - "v" => Matrix => {" with entries in ",TO ZZ," or ",TO QQ," and only one column representing a vector"} - }, - Outputs => { - "P1" => Polyhedron - }, - - PARA{}, TT "A"," must be a matrix from some source space to the ambient space of the polyhedron ",TT "P"," - and ",TT "v"," must be a vector in that ambient space, i.e. the number of - rows of ",TT "A"," must equal the ambient dimension of ",TT "P"," and the number of rows - of ",TT "v",". ",TT "affinePreimage"," then computes the polyhedron ",TT "{q | (A*q)+v in P}"," - where ",TT "v"," is set to 0 if omitted and ",TT "A"," is the identity if omitted.", - - PARA{}, "For example, consider the following two dimensional polytope", - - EXAMPLE { - " P = convexHull matrix {{-2,0,2,4},{-8,-2,2,8}}", - }, - - PARA{}, "and its affine preimage under the following map:", - - EXAMPLE { - " A = matrix {{-5,2},{3,-1}}", - " v = matrix {{5},{-3}}", - " Q = affinePreimage(A,P,v)", - " vertices Q", - } - - } - -document { - Key => {bipyramid, (bipyramid,Polyhedron)}, - Headline => "computes the bipyramid over a polyhedron", - Usage => " Q = bipyramid P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "The ",TT "bipyramid"," over a ",TO Polyhedron," in n-space is constructed by - embedding the Polyhedron into (n+1)-space, computing the barycentre of the vertices, - which is a point in the relative interior, and taking the convex hull of the embedded - Polyhedron and the barycentre ",TT "x {+/- 1}",".", - - PARA{}, "As an example, we construct the octahedron as the bipyramid over the square - (see ",TO hypercube,").", - - EXAMPLE { - " P = hypercube 2", - " Q = bipyramid P", - " vertices Q", - } - - } - -document { - Key => {ccRefinement, (ccRefinement,Matrix)}, - Headline => "computes the coarsest common refinement of a set of rays", - Usage => " F = ccRefinement R", - Inputs => { - "R" => Matrix - }, - Outputs => { - "F" => Fan - }, - - PARA{}, "The coarsest common refinement of a set of rays ",TT "R"," is the common refinement - of all possible triangulations of the rays.", - - PARA{}, "For example, consider a three dimensional cone with four rays:", - - EXAMPLE { - " R = matrix {{1,1,-1,-1},{1,-1,1,-1},{1,1,1,1}}" - }, - - PARA{}, "The coarsest common refinement has a fifth ray and consists of four cones.", - - EXAMPLE { - " F = ccRefinement R", - " rays F" - } - - } - -document { - Key => {coneToPolyhedron, (coneToPolyhedron,Cone)}, - Headline => "converts a cone to class Polyhedron", - Usage => " P = coneToPolyhedron C", - Inputs => { - "C" => Cone - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "Every ",TO Cone," is in particular a ",TO Polyhedron,". ",TT "coneToPolyhedron"," - converts the cone into the same cone but of class ",TO Polyhedron,".", - - PARA{}, "Consider the positive orthant in ",TO QQ,"^3:", - - EXAMPLE { - " C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}" - }, - - PARA{}, "If we want to consider the positive orthant not as cone but as a polyhedron we - apply ",TT "coneToPolyhedron",":", - - EXAMPLE { - " P = coneToPolyhedron C" - }, - - PARA{}, "Although, they are the same geometric object but of different classes, Polyhedra - considers them not as equal:", - - EXAMPLE { - " P === C" - } - } - -document { - Key => directProduct, - Headline => "computes the direct product of two convex objects", - - } - -document { - Key => {(directProduct,Cone,Cone), (directProduct,Cone,Polyhedron), - (directProduct,Polyhedron,Cone), (directProduct,Polyhedron,Polyhedron)}, - Headline => "computes the direct product of polyhedra and cones", - Usage => " P = directProduct(X,Y)", - Inputs => { - "X" => {TO Cone," or ",TO Polyhedron}, - "Y" => {TO Cone," or ",TO Polyhedron} - }, - Outputs => { - "P" => {TO Cone," or ",TO Polyhedron} - }, - - PARA{}, "The ", TT "directProduct"," of ",TT "X"," and ",TT "Y"," is the polyhedron - ",TT "{(x,y) | x in X, y in Y}"," in the direct product of the ambient spaces. If - ",TT "X"," and ",TT "Y"," are both cones, then the direct product is again a cone - and the output is then also given as a ",TO Cone,", otherwise as a ",TO Polyhedron,".", - - EXAMPLE { - " P = hypercube 1", - " Q = hypercube 2", - " directProduct(P,Q) == hypercube 3" - }, - - PARA{}, "See also ",TO (symbol *,Cone,Cone),", ",TO (symbol *,Cone,Polyhedron),", ", - TO (symbol *,Polyhedron,Cone),", and ",TO (symbol *,Polyhedron,Polyhedron),"." - - } - -document { - Key => (directProduct,Fan,Fan), - Headline => "computes the direct product of two fans", - Usage => " F = directProduct(F1,F2)", - Inputs => { - "F1" => Fan, - "F2" => Fan - }, - Outputs => { - "F" => Fan - }, - - PARA{}, "The ",TT "directProduct"," of two fans is the fan given by ",TT "C = C1 x C2"," - for all cones ",TT "C1 in F1"," and ",TT "C2 in F2"," in the direct product of the - ambient spaces.", - - EXAMPLE { - " F1 = normalFan hypercube 1", - " F2 = normalFan hypercube 2", - " F = directProduct(F1,F2)", - " F == normalFan hypercube 3" - }, - - PARA{}, "See also ", TO (symbol *,Fan,Fan),"." - - } - -document { - Key => {dualCone, (dualCone,Cone)}, - Headline => " computes the dual Cone", - Usage => " Cv = dualCone C", - Inputs => { - "C" => Cone - }, - Outputs => { - "Cv" => Cone - }, - - PARA{}, "The dual cone of ",TT "C"," in ",TO QQ,"^n is the cone in the dual ambient - space (",TO QQ,"^n)^*, given - by ",TT "{p in (",TO QQ,TT "^n)^* | p*c >= 0 for all c in C}",".", - - EXAMPLE { - " C = posHull matrix {{1,2},{2,1}}", - " Cv = dualCone C", - " rays Cv" - } - - } - -document { - Key => { imageFan, (imageFan,Matrix,Cone)}, - Headline => " computes the fan of the image", - Usage => " F = imageFan(M,C)", - Inputs => { - "M" => Matrix, - "C" => Cone - }, - Outputs => { - "F" => Fan - }, - - PARA{}, TT "M"," must be a matrix from the ambient space of the ",TO Cone," ",TT "C"," to some - target space. The ",TT "imageFan"," is the common refinement of the images of all faces of ",TT "C",".", - - EXAMPLE { - " C = posHull matrix {{2,1,-1,-3},{1,1,1,1},{0,1,-1,0}}", - " M = matrix {{1,0,0},{0,1,0}}", - " F = imageFan(M,C)", - " rays F" - } - - } - -document { - Key => { minkowskiSum, (minkowskiSum,Cone,Cone), (minkowskiSum,Cone,Polyhedron), - (minkowskiSum,Polyhedron,Cone), (minkowskiSum,Polyhedron,Polyhedron)}, - Headline => " computes the Minkowski sum of two convex objects", - Usage => " Q = minkowskiSum(X,Y)", - Inputs => { - "X" => {TO Cone," or ",TO Polyhedron}, - "Y" => {TO Cone," or ",TO Polyhedron} - }, - Outputs => { - "Q" => {TO Cone," or ",TO Polyhedron} - }, - - PARA{}, "The Minkowski sum of ",TT "X"," and ",TT "Y"," is the polyhedron - ",TT "X + Y = {x + y | x in X, y in Y}",". If ",TT "X"," and ",TT "Y"," are both - cones, then their Minkowski sum is their positive hull, which is a cone, so the - output is a ",TO Cone,". Otherwise the output is a ",TO Polyhedron,". ",TT "X"," - and ",TT "Y"," have to lie in the same ambient space.", - - EXAMPLE { - " P1 = convexHull matrix {{0,1,-1},{0,-1,-1}}", - " P2 = convexHull matrix {{0,1,-1},{0,1,1}}", - " Q = minkowskiSum(P1,P2)", - " vertices Q" - }, - - PARA{}, "See also ",TO (symbol +,Cone,Cone),", ",TO (symbol +,Cone,Polyhedron),", ", - TO (symbol +,Polyhedron,Cone),", and ",TO (symbol +,Polyhedron,Cone),"." - - } - -document { - Key => {normalFan, (normalFan,Polyhedron)}, - Headline => "computes the normalFan of a polyhedron", - Usage => " F = normalFan P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "F" => Fan - }, - - PARA{}, "The ",TT "normalFan"," of a ",TO Polyhedron," is the fan generated by the - cones ",TT "C_v"," for all vertices ",TT "v"," of the ",TO Polyhedron,", - where ",TT "C_v"," is the dual Cone of the positive Hull of ",TT "P-v",". - If ",TT "P"," is compact, i.e. a polytope, then the normalFan is complete.", - - EXAMPLE { - " P = convexHull matrix{{1,0,0},{0,1,0}}", - " F = normalFan P", - " apply(genCones F,rays)" - } - - } - -document { - Key => {polar, (polar,Polyhedron)}, - Headline => " computes the polar of a polyhedron", - Usage => " Pv = polar P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "Pv" => Polyhedron - }, - - PARA{}, "The polar polyhedron of ",TT "P"," in n-space is the polyhedron in the dual - space given by ",TT "{v in (QQ^n)^* | v*p >= -1 for all p in P}",".", - - EXAMPLE { - " P = hypercube 3", - " Q = polar P", - " Q == crossPolytope 3" - } - - } - -document { - Key => {pyramid, (pyramid,Polyhedron)}, - Headline => "computes the pyramid over a polyhedron", - Usage => " Q = pyramid P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, TT "pyramid"," takes the polyhedron ",TT "P"," with ambient dimension n - and embeds it into ",TO QQ,"^(n+1) on height 0 with respect to the new last variable. - Then it computes the convex hull of the embedded ",TT "P"," and the point (0,...,0,1).", - - EXAMPLE { - " P = hypercube 2", - " Q = pyramid P", - " vertices Q" - } - - } - -document { - Key => {sublatticeBasis, (sublatticeBasis,Matrix), (sublatticeBasis,Polyhedron)}, - Headline => "computes a basis for the sublattice generated by integral vectors or the lattice points of a polytope", - Usage => " B = sublatticeBasis M \nB = sublatticeBasis P", - Inputs => { - "M" => Matrix => {" over ",TO ZZ," with each column representing a sublattice generator"}, - "P" => Polyhedron, - }, - Outputs => { - "B" => {"A matrix over ", TO ZZ," containing a sublattice basis"} - }, - - PARA{}, TT "sublatticeBasis"," computes a basis for the sublattice generated by the columns of",TT "M"," or - by the lattice points of",TT "P",".", - - EXAMPLE { - " P = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0},{1,1,3}}", - " sublatticeBasis P" - } - } - -document { - Key => {toSublattice, (toSublattice,Polyhedron)}, - Headline => "calculates the preimage of a polytope in the sublattice generated by its lattice points", - Usage => "Q = toSublattice P", - Inputs => { - "P" => Polyhedron => {"which must be compact"} - }, - Outputs => { - "Q" => Polyhedron => {"preimage of P in the sublattice generated by its lattice points"} - }, - - PARA{}, TT "toSublattice"," can only be applied to polytopes, i.e. compact polyhedra. It - calculates a basis of the sublattice generated by its lattice points, and then takes the affine - preimage under the corresponding map.", - - EXAMPLE { - " P = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0},{1,1,3}}", - " toSublattice P" - } - - } - -document { - Key => {crossPolytope, (crossPolytope,ZZ), (crossPolytope,ZZ,QQ), (crossPolytope,ZZ,ZZ)}, - Headline => "computes the d-dimensional crosspolytope with diameter 2s", - Usage => " P = crossPolytope(d,s)", - Inputs => { - "d" => ZZ => {" strictly positive"}, - "s" => {TO ZZ," or ",TO QQ,", positive (optional)"} - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "The ",TT "d","-dimensional ",TT "crossPolytope"," with diameter ",TT "s"," is the - convex hull of ",TT "+/- s"," times the standard basis in ",TO QQ,"^d. If ",TT "s"," is omitted - it is set to 1.", - - EXAMPLE { - " P = crossPolytope(3,3/2)", - " vertices P" - } - - } - -document { - Key => {cyclicPolytope, (cyclicPolytope,ZZ,ZZ)}, - Headline => "computes the d dimensional cyclic polytope with n vertices", - Usage => " P = cyclicPolytope(d,n)", - Inputs => { - "d" => ZZ => {"strictly positive"}, - "n" => ZZ => {"strictly positive"} - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "The ",TT "d","-dimensional ",TT "cyclicPolytope"," with ",TT "n"," vertices - is the convex hull of ",TT "n"," points on the moment curve in ",TO QQ,"^",TT "d",". The - moment curve is defined by ",TT "t -> (t,t^2,...,t^d)"," and the function takes the - points ",TT "{0,...,n-1}",".", - - EXAMPLE { - " P = cyclicPolytope(3,5)", - " vertices P" - } - - } - -document { - Key => {ehrhart, (ehrhart,Polyhedron)}, - Headline => "calculates the Ehrhart polynomial of a polytope", - Usage => "f = ehrhart P", - Inputs => { - "P" => Polyhedron => {"which must be compact"} - }, - Outputs => { - "f" => RingElement => {"Ehrhart polynomial as element of QQ[x]"} - }, - - PARA{}, TT "ehrhart"," can only be applied to polytopes, i.e. compact polyhedra. - To calculate the Ehrhart polynomial, the number of lattice points in the first n - dilations of the polytope are calculated, where n is the dimension of the polytope. - A system of linear equations is then solved to find the polynomial.", - - EXAMPLE { - " P = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0},{1,1,3}}", - " ehrhart P" - } - - } - -document { - Key => {emptyPolyhedron, (emptyPolyhedron,ZZ)}, - Headline => "generates the empty polyhedron in n-space", - Usage => " P = emptyPolyhedron n", - Inputs => { - "n" => ZZ => {"strictly positive"} - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "Generates the empty polyhedron in ",TT "n","-space.", - - EXAMPLE { - " P = emptyPolyhedron 3" - } - - } - -document { - Key => {hirzebruch, (hirzebruch,ZZ)}, - Headline => "computes the fan of the r-th Hirzebruch surface", - Usage => " F = hirzebruch r", - Inputs => { - "r" => ZZ => {"positive"} - }, - Outputs => { - "F" => Fan - }, - - PARA{}, "The ",TT "r","-th Hirzebruch surface is the ",TO Fan," in ",TO QQ,"^2 generated - by the cones , , <-e_1+r*e_2,-e_2> and <-e_1+r*e_2,e_2>.", - - EXAMPLE { - " F = hirzebruch 3", - " apply(genCones F,rays)" - } - - } - -document { - Key => {hypercube, (hypercube,ZZ), (hypercube,ZZ,QQ), (hypercube,ZZ,ZZ)}, - Headline => "computes the d-dimensional hypercube with edge length 2*s", - Usage => " P = hypercube(d,s)", - Inputs => { - "d" => ZZ => {", strictly positive"}, - "s" => {TO ZZ," or ",TO QQ,", positive (optional)"} - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "The ",TT "d","-dimensional ",TT "hypercube"," with edge length 2*",TT "s"," is - the convex hull of all points in ",TT "{+/- s}^d"," in ",TO QQ,"^d. If ",TT "s"," is omitted - it is set to 1.", - - EXAMPLE { - " P = hypercube 3", - " vertices P" - } - - } - -document { - Key => {newtonPolytope, (newtonPolytope,RingElement)}, - Headline => "computes the Newton polytope of a polynomial", - Usage => "P = newtonPolytope f", - Inputs => { - "f" => RingElement - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "The ",TT "newtonPolytope"," of ",TT "f"," is the convex hull of its - exponent vectors in n-space, where n is the number of variables in the ring.", - - PARA{}, "Consider the Vandermond determinant in 3 variables:", - - EXAMPLE { - " R = QQ[a,b,c]", - " f = (a-b)*(a-c)*(b-c)" - }, - - PARA{}, "If we compute the Newton polytope we get a hexagon in ",TT "QQ","^3.", - - EXAMPLE { - " P = newtonPolytope f" - } - - } - -document { - Key => {posOrthant, (posOrthant,ZZ)}, - Headline => "generates the positive orthant in n-space", - Usage => " C = posOrthant n", - Inputs => { - "n" => ZZ => {"strictly positive"} - }, - Outputs => { - "C" => Cone - }, - - PARA{}, "Generates the positive orthant in the n dimensional space as a cone.", - - EXAMPLE { - " C = posOrthant 3", - " rays C" - } - } - -document { - Key => {statePolytope, (statePolytope,Ideal)}, - Headline => "computes the state polytope of a homogeneous ideal", - Usage => " P = statePolytope I", - Inputs => { - "I" => Ideal => {"which must be homogeneous"} - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "A ",TT "statePolytope"," of an Ideal ",TT "I"," has as normalFan - the Groebner fan of the ideal. We use the construction by Sturmfels, see Algorithm 3.2 in ", - HREF("http://math.berkeley.edu/~bernd/index.html", "Bernd Sturmfels'"), " ", EM "Groebner Bases and - Convex Polytopes", ", volume 8 of University Lecture Series. American Mathematical Society, - first edition, 1995.", - - PARA{}, "Consider the following ideal in a ring with 3 variables:", - - EXAMPLE { - " R = QQ[a,b,c]", - " I = ideal (a-b,a-c,b-c)" - }, - - PARA{}, "The state polytope of this ideal is a triangle in 3 space, because the ideal has three - initial ideals:", - - EXAMPLE { - " statePolytope I" - }, - - PARA{}, "The generators of the three initial ideals are given in the first part of the result." - - } - -document { - Key => {stdSimplex, (stdSimplex,ZZ)}, - Headline => "generates the d-dimensional standard simplex", - Usage => " P = stdSimplex d", - Inputs => { - "d" => ZZ => {"strictly positive"} - }, - Outputs => { - "P" => Polyhedron - }, - - PARA{}, "The ",TT "d","-dimensional standard simplex is the convex hull of the - standard basis in ",TO QQ,"^(d+1).", - - EXAMPLE { - " P = stdSimplex 2", - " vertices P" - } - - } - -document { - Key => (symbol *,Cone,Cone), - Headline => "computes the direct product of two cones", - Usage => " C = C1 * C2", - Inputs => { - "C1" => Cone, - "C2" => Cone - }, - Outputs => { - "C" => Cone - }, - - PARA{}, "Computes the direct product of ",TT "C1"," and ",TT "C2",". This is the cone - ",TT "{(x,y) | x in C1, y in C2}",", in the direct product of the ambient spaces.", - - PARA{}, "See also ",TO directProduct,".", - - EXAMPLE { - " C1 = posHull matrix {{1,2},{2,1}}", - " C2 = posHull matrix {{1}}", - " C = C1 * C2", - " rays C" - } - - } - -document { - Key => (symbol *,Cone,Polyhedron), - Headline => "computes the direct product of a cone and a polyhedron", - Usage => " Q = C * P", - Inputs => { - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the direct product of ",TT "C"," and ",TT "P",". This is the - polyhedron ",TT "{(c,p) | c in C, p in P}",", in the direct product of the ambient spaces.", - - PARA{}, "See also ",TO directProduct,".", - - EXAMPLE { - " C = posHull matrix {{1,2},{2,1}}", - " P =convexHull matrix {{1},{-1}}", - " Q = C * P", - " (vertices Q,rays Q)" - } - - } - -document { - Key => (symbol *,Polyhedron,Cone), - Headline => "computes the direct product of a polyhedron and a cone", - Usage => " Q = P * C", - Inputs => { - "P" => Polyhedron, - "C" => Cone - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the direct product of ",TT "P"," and ",TT "C",". This is the polyhedron - ",TT "{(p,c) | p in P, x in C}",", in the direct product of the ambient spaces.", - - PARA{}, "See also ",TO directProduct,".", - - EXAMPLE { - " P =convexHull matrix {{1},{-1}}", - " C = posHull matrix {{1,2},{2,1}}", - " Q = P * C", - " (vertices Q,rays Q)" - } - - } - -document { - Key => (symbol *,Polyhedron,Polyhedron), - Headline => "computes the direct product of two polyhedra", - Usage => " Q = P1 * P2", - Inputs => { - "P1" => Polyhedron, - "P2" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the direct product of ",TT "P1"," and ",TT "P2",".This is the polyhedron - ",TT "{(x,y) | x in P1, y in P2}",", in the direct product of the ambient spaces.", - - PARA{}, "See also ",TO directProduct,".", - - EXAMPLE { - " P1 = convexHull matrix {{1,-1,0,0},{0,0,1,-1}}", - " P2 = convexHull matrix {{1},{-1}}", - " P = P1 * P2", - " vertices P" - } - - } - -document { - Key => (symbol *,Fan,Fan), - Headline => "computes the direct product", - Usage => " F = F1 * F2", - Inputs => { - "F1" => Fan, - "F2" => Fan - }, - Outputs => { - "F" => Fan - }, - - PARA{}, "Computes the direct product of two fans. This is the fan given by ",TT "C=C1 x C2"," - for all cones ",TT "C1 in F1"," and ",TT "C2 in F2",", in the direct product of the - ambient spaces.", - - PARA{}, "See also ",TO (directProduct,Fan,Fan),".", - - EXAMPLE { - " F1 = normalFan hypercube 1", - " F2 = normalFan hypercube 2", - " F = F1 * F2", - " F == normalFan hypercube 3" - } - - } - -document { - Key => {(symbol *,QQ,Polyhedron), (symbol *,ZZ,Polyhedron)}, - Headline => "rescales a polyhedron by a given positive factor", - Usage => " Q = k * P", - Inputs => { - "k" => {TO ZZ," or ",TO QQ,", strictly positive"}, - "P" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Rescales the ",TO Polyhedron," by the strictly positive factor - ",TT "k",".", - - EXAMPLE { - " P = crossPolytope 3", - " k = 3", - " Q = k * P", - " vertices Q" - } - } - -document { - Key => (symbol +,Cone,Cone), - Headline => "computes the Minkowski sum of two cones", - Usage => " C = C1 + C2", - Inputs => { - "C1" => Cone, - "C2" => Cone - }, - Outputs => { - "C" => Cone - }, - - PARA{}, "Computes the Minkowski sum of ",TT "C1"," and ",TT "C2",". This is the cone - ",TT "C1 + C2 = {x + y | x in C1, y in C2}",". Note that ",TT "C1"," and ",TT "C2"," have - to lie in the same ambient space.", - - PARA{}, "See also ",TO minkowskiSum,".", - - EXAMPLE { - " C1 = posHull matrix {{1,2,3},{2,3,1},{3,1,2}}", - " C2 = posHull matrix {{1},{0},{0}}", - " C = C1 + C2", - " rays C" - } - - } - -document { - Key => (symbol +,Cone,Polyhedron), - Headline => "computes the Minkowski sum of a cone and a polyhedron", - Usage => " Q = C + P", - Inputs => { - "C" => Cone, - "P" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the Minkowski sum of ",TT "C"," and ",TT "P",".This is the polyhedron - ",TT "C + P = {c + p | c in C, p in P}",". Note that ",TT "C"," and ",TT "P"," have - to lie in the same ambient space.", - - PARA{}, "See also ",TO minkowskiSum,".", - - EXAMPLE { - " C = posHull matrix {{1},{2},{0}}", - " P = hypercube 3", - " Q = C + P", - " (vertices Q,rays Q)" - } - - } - -document { - Key => (symbol +,Polyhedron,Cone), - Headline => "computes the Minkowski sum of a polyhedron and a cone", - Usage => " Q = P + C", - Inputs => { - "P" => Polyhedron, - "C" => Cone - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the Minkowski sum of ",TT "P"," and ",TT "C",". This is the polyhedron - ",TT "P + C = {p + c | p in P, c in C}",". Note that ",TT "P"," and ",TT "C"," have - to lie in the same ambient space.", - - PARA{}, "See also ",TO minkowskiSum,".", - - EXAMPLE { - " P = hypercube 2", - " C = posHull matrix {{1},{2}}", - " Q = P + C", - " (vertices Q,rays Q)" - } - - } - -document { - Key => (symbol +,Polyhedron,Polyhedron), - Headline => "computes the Minkowski sum of two polyhedra", - Usage => " Q = P1 + P2", - Inputs => { - "P1" => Polyhedron, - "P2" => Polyhedron - }, - Outputs => { - "Q" => Polyhedron - }, - - PARA{}, "Computes the Minkowski sum of ",TT "P1"," and ",TT "P2",".This is the polyhedron - ",TT "P1 + P2 = {x + y | x in P1, y in P2}",". Note that ",TT "P1"," and ",TT "P2"," have - to lie in the same ambient space.", - - PARA{}, "See also ",TO minkowskiSum,".", - - EXAMPLE { - " P1 = convexHull matrix {{1,0,0},{0,1,0}}", - " P2 = convexHull matrix {{-1,0,0},{0,-1,0}}", - " P = P1 + P2", - " vertices P" - } - - } - -document { - Key => (symbol ==,Cone,Cone), - Headline => "equality", - Usage => " C1 == C2", - Inputs => { - "C1" => Cone, - "C2" => Cone - } - - } - -document { - Key => (symbol ==,Fan,Fan), - Headline => "equality", - Usage => " F1 == F2", - Inputs => { - "F1" => Fan, - "F2" => Fan - } - - } - -document { - Key => (symbol ==,Polyhedron,Polyhedron), - Headline => "equality", - Usage => " P1 == P2", - Inputs => { - "P1" => Polyhedron, - "P2" => Polyhedron - } - - } - -document { - Key => (dim,Cone), - Headline => "computes the dimension of a cone", - Usage => " d = dim C", - Inputs => { - "C" => Cone - }, - Outputs => { - "d" => ZZ - }, - - PARA{}, "Returns the dimension of a cone.", - - EXAMPLE { - " C = posHull matrix {{2,3},{3,2}}", - " dim C" - } - - } - -document { - Key => (dim,Fan), - Headline => "computes the dimension of a fan", - Usage => " d = dim F", - Inputs => { - "F" => Fan - }, - Outputs => { - "d" => ZZ - }, - - PARA{}, "Returns the dimension of a fan. This - is the maximal dimension of all cones of - the fan.", - - EXAMPLE { - " F = hirzebruch 3", - " dim F" - } - - } - -document { - Key => (dim,Polyhedron), - Headline => "computes the dimension of a polyhedron", - Usage => " d = dim P", - Inputs => { - "P" => Polyhedron - }, - Outputs => { - "d" => ZZ - }, - - PARA{}, "Returns the dimension of a polyhedron.", - - EXAMPLE { - " P = convexHull matrix {{1,-1,0,0},{0,0,1,-1}}", - " dim P" - } - - } - -document { - Key => (net,Cone), - Headline => "displays characteristics of a cone", - Usage => " net C", - Inputs => { - "C" => Cone - }, - - PARA{}, "Displays an overview of the properties of the - cone, the ambient dimension, the dimension of the lineality - space, the dimension of the cone, the number of facets, and - the number of rays.", - - EXAMPLE { - " C = posHull matrix {{1,2,3},{2,3,1},{3,1,2},{1,0,1}};", - " net C" - } - - } - -document { - Key => (net,Fan), - Headline => "displays characteristics of a fan", - Usage => " net F", - Inputs => { - "F" => Fan - }, - - PARA{}, "Displays an overview of the properties of the - Fan, the ambient dimension, the number of generating - cones, the number of rays, and the top dimension of - the cones.", - - EXAMPLE { - " F = normalFan cyclicPolytope(3,5);", - " net F" - } - - } - -document { - Key => (net,Polyhedron), - Headline => "displays characteristics of a polyhedron", - Usage => " net P", - Inputs => { - "P" => Polyhedron - }, - - PARA{}, "Displays an overview of the properties of the - Polyhedron, the ambient dimension, the dimension of the - lineality space, the dimension of the polyhedron, the - number of facets, the number of rays, and the number of - vertices.", - - EXAMPLE { - " P = cyclicPolytope(4,6);", - " net P" - } - - } - -document { - Key => {saveSession,(saveSession,String)}, - Headline => "save the actual Polyhedra session to a file", - Usage => " saveSession F", - Inputs => { - "F" => String - }, - - PARA{}, "All convex polyhedral objects (",TO Cone,",",TO Fan,",",TO Polyhedron,") that have been assigned - to a ",TO Symbol," will be saved into the file ",TT "F",". If the package ",TT "PPDivisor"," is loaded, then - also all ",TT "PolyhedralDivisors"," are saved into ",TT "F",". Also every ",TO List," or ",TO Sequence," - containing any of the above types or lists and sequences of them in arbitrary nested depth of lists is saved.", - - PARA{}, "To recover the session simply call ",TT "load F",". It is not necessary that ",TT "Polyhedra"," is already - loaded (if not, it will be) and also ",TT "PPDivisor"," is loaded if it was loaded when the session had been saved." - - } - - --- Test 0 --- Checking convexHull basics -TEST /// -P = convexHull matrix {{3,1,0,2},{0,2,2,1},{1,-1,2,0}}; -assert(P#"number of vertices" == 3) -assert(dim P == 2) -assert(ambDim P == 3) -assert(rays P == 0) -assert(linSpace P == 0) -M = matrix {{3_QQ,4,1}}; -v = matrix {{10_QQ}}; -assert(hyperplanes P == (M,v) or hyperplanes P == (-M,-v)) -/// - --- Test 1 --- Checking convexHull basics -TEST /// -P = convexHull matrix {{3,1,0,2},{0,2,2,1},{1,-1,2,0}}; -P = convexHull {P,(matrix{{4},{0},{-2}},matrix{{1,0,0},{0,1,-1},{0,0,0}})}; -assert(dim P == 3) -assert(image linSpace P == image matrix {{0},{1_QQ},{0}}) -assert(hyperplanes P == (0,0)) -/// - --- Test 2 --- Checking convexHull halfspaces -TEST /// -P = convexHull (matrix{{1},{1}},matrix{{1,0},{0,1}}); -M1 = matrix {{-1,0_QQ},{0,-1}}; -M2 = matrix {{0,-1_QQ},{-1,0}}; -v = matrix {{-1},{-1_QQ}}; -assert(halfspaces P == (M1,v) or halfspaces P == (M2,v)) -/// - --- Test 3 --- Checking convexHull and intersection -TEST /// -P2 = convexHull matrix {{1,-2,-1,2},{2,1,-2,-1}}; -M = matrix{{3,1},{-3,-1},{1,-3},{-1,3}}; -v = matrix{{5},{5},{5},{5}}; -assert(intersection(M,v) == P2) -/// - --- Test 4 --- Checking intersection -TEST /// -P = intersection (matrix{{1,0},{0,1},{-1,0},{0,-1}},matrix{{1},{2},{3},{4}}); -V1 = vertices P; -V1 = set apply(numColumns V1, i -> V1_{i}); -V2 = set {matrix{{1_QQ},{2}},matrix{{1_QQ},{-4}},matrix{{-3_QQ},{2}},matrix{{-3_QQ},{-4}}}; -assert(isSubset(V1,V2) and isSubset(V2,V1)) -/// - --- Test 5 --- Checking polar -TEST /// -P = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1}}; -Q = convexHull matrix {{1,-1,0,0},{0,0,1,-1}}; -P = polar P; -assert(P == Q) -P = convexHull(matrix {{1,-1,1,-1},{1,1,-1,-1},{1,2,3,4}},matrix {{0,0},{0,0},{1,-1}}); -Q = convexHull matrix {{1,-1,0,0},{0,0,1,-1},{0,0,0,0}}; -P = polar P; -assert(P == Q) -/// - --- Test 6 --- Checking intersections that give cones -TEST /// -C = intersection matrix {{1,2},{2,1}}; -R1 = rays C; -R1 = set apply(numColumns R1, i -> R1_{i}); -R2 = set {matrix{{2_QQ},{-1}},matrix{{-1_QQ},{2}}}; -assert(isSubset(R1,R2) and isSubset(R2,R1)) -assert(linSpace C == 0) -assert(dim C == 2) -assert(ambDim C == 2) -/// - --- Test 7 --- Checking intersection that give a not pointed cone and intersection for lists -TEST /// -C = intersection matrix {{1,2,1},{2,1,1}}; -assert(image linSpace C == image matrix{{1_QQ},{1_QQ},{-3}}) -assert(ambDim C == 3) -P = intersection {hypercube 3,C,(matrix{{1,1,1}},matrix{{1}})}; -V = matrix {{1/3,1,0,1,1,-1,-1/3},{1/3,0,1,1,-1,1,-1/3},{-1,-1,-1,-1,1,1,1}}; -assert(vertices P == V); -/// - --- Test 8 --- Checking posHull -TEST /// -C = posHull(matrix{{1,0},{0,1},{0,0}},matrix{{0},{0},{1}}); -assert(halfspaces C == matrix{{1_QQ,0,0},{0,1,0}} or halfspaces C == matrix{{0_QQ,1,0},{1,0,0}}) -assert(C#"number of rays" == 2) -/// - --- Test 9 --- Checking contains for polyhedra -TEST /// -P1 = convexHull matrix {{0,1,1,0},{0,0,1,1}}; -P2 = convexHull matrix {{0,2,0},{0,0,2}}; -assert contains(P2,P1) -assert(not contains(P1,P2)) -P1 = convexHull(matrix {{0,1,1,0},{0,0,1,1},{0,0,0,0}},matrix {{0},{0},{1}}); -P2 = convexHull matrix {{0,1,1,0},{0,0,1,1},{1,2,3,4}}; -assert(not contains(P2,P1)) -assert contains(P1,P2) -/// - --- Test 10 --- Checking contains for cones -TEST /// -C1 = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -C2 = posHull matrix {{1},{1},{1}}; -assert contains(C1,C2) -assert(not contains(C2,C1)) -C2 = posHull {C2, matrix {{1,-1,0,0},{0,0,1,-1},{0,0,0,0}}}; -assert contains(C2,C1) -assert(not contains(C1,C2)) -/// - --- Test 11 --- Checking equality for polyhedra and cones -TEST /// -P = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1}}; -Q = intersection(matrix{{1,0},{-1,0},{0,1},{0,-1}},matrix{{1},{1},{1},{1}}); -assert(P == Q) -C1 = posHull matrix {{1,2},{2,1}}; -C2 =intersection matrix {{2,-1},{-1,2}}; -assert(C1 == C2) -/// - --- Test 12 --- Checking dualCone -TEST /// -C1 = posHull matrix {{1,2,3},{2,3,1},{3,1,2}}; -C2 = posHull matrix {{-5,7,1},{1,-5,7},{7,1,-5}}; -C1 = dualCone C1; -assert(C1 == C2) -C1 = intersection matrix {{0,1,2,3},{1,2,3,0},{2,3,0,1}}; -C2 = intersection matrix {{7,-5,1,1},{0,1,4,-3},{0,9,-6,1},{0,-3,2,9},{-7,5,-1,-1}}; -C1 = dualCone C1; -assert(C1 == C2) -/// - --- Test 13 --- Checking faces and minkSummandCone -TEST /// -P = convexHull matrix {{0,-1,1,0,0,1,-1},{0,0,0,1,-1,-1,1}}; -F1 = faces(1,P); -F2 = {convexHull matrix{{-1,0},{1,1}},convexHull matrix{{0,1},{1,0}},convexHull matrix{{1,1},{0,-1}},convexHull matrix{{1,0},{-1,-1}},convexHull matrix{{0,-1},{-1,0}},convexHull matrix{{-1,-1},{0,1}}}; -assert(set F1 === set F2) -(C,L,M) = minkSummandCone(P); -assert(rays(C)*M == matrix{{1_QQ,1},{1,1},{1,1},{1,1},{1,1},{1,1}}) -L1 = {convexHull matrix{{0,1},{0,0}},convexHull matrix{{0,0},{0,1}},convexHull matrix{{0,1},{0,-1}},convexHull matrix{{0,0,1},{0,1,0}},convexHull matrix{{0,1,1},{0,0,-1}}}; -assert(set values L === set L1) -/// - --- Test 14 --- Checking bipyramid, faces and fVector -TEST /// -P = convexHull matrix {{0,-1,1,0,0,1,-1},{0,0,0,1,-1,-1,1}}; -P = bipyramid P; -F1 = set apply(faces(3,P), f -> vertices f); -F2 = set {matrix{{-1_QQ},{0},{0}},matrix{{1_QQ},{0},{0}},matrix{{0_QQ},{1},{0}},matrix{{0_QQ},{-1},{0}},matrix{{1_QQ},{-1},{0}},matrix{{-1_QQ},{1},{0}},matrix{{0_QQ},{0},{1}},matrix{{0_QQ},{0},{-1}}}; -assert(isSubset(F1,F2) and isSubset(F2,F1)) -assert(fVector P == {8,18,12,1}) -/// - --- Test 15 --- Checking isEmpty -TEST /// -P = intersection(matrix{{1,1,1},{-1,0,0},{0,-1,0},{0,0,-1}},matrix{{1},{0},{0},{0}}); -assert not isEmpty P -P = intersection {P,(matrix{{-1,-1,-1}},matrix{{-2}})}; -assert isEmpty P -/// - --- Test 16 --- Checking isPointed -TEST /// -C = posHull matrix {{1,1,1,1},{1,-1,1,-1},{1,1,-1,-1}}; -assert isPointed C -C = posHull {C,matrix{{-1},{0},{-1}}}; -assert not isPointed C -/// - --- Test 17 --- Checking isSmooth -TEST /// -C = posHull matrix {{1,0,0},{-1,2,3},{1,1,2}}; -assert isSmooth C -C = posHull {C,matrix{{1},{0},{2}}}; -assert not isSmooth C -C = posHull matrix {{1,2},{2,1},{1,2}}; -assert not isSmooth C -C = posHull matrix {{1,1,-1,-1},{1,2,1,-1},{1,3,0,-1}}; -assert not isSmooth C -C = posHull {C,matrix{{1},{0},{1}}}; -assert isSmooth C -/// - --- Test 18 --- Checking is Face -TEST /// -C1 = posHull matrix {{1,1,1,1},{1,-1,0,0},{0,0,1,-1}}; -C2 = posHull matrix {{1,1},{1,-1},{0,0}}; -assert not isFace(C2,C1) -C2 = posHull matrix {{1},{1},{1}}; -assert not isFace(C2,C1) -C2 = posHull matrix {{1},{0},{-1}}; -assert isFace(C2,C1) -C2 = posHull matrix {{0},{0},{0}}; -assert isFace(C2,C1) -/// - --- Test 19 --- Checking isFace -TEST /// -P1 = convexHull matrix {{1,1,1,1,-1,-1,-1,-1},{1,1,-1,-1,1,1,-1,-1},{1,-1,1,-1,1,-1,1,-1}}; -P2 = intersection(matrix {{1,0,0},{-1,0,0}},matrix {{-1},{-1}}); -assert isFace(P2,P1) -P2 = convexHull matrix {{1,1,1},{1,1,-1},{1,-1,1}}; -assert not isFace(P2,P1) -P2 = intersection {P2,{matrix{{0,1,0}},matrix{{1}}}}; -assert isFace(P2,P1) -/// - --- Test 20 --- Checking isCompact -TEST /// -P = intersection(matrix {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1}},matrix {{1},{2},{3},{4},{5}}); -assert not isCompact P -P = intersection {P, (matrix {{0,0,-1}},matrix {{6}})}; -assert isCompact P -P = intersection {P, {matrix {{1,1,1}},matrix {{0}}}}; -assert isCompact P -/// - --- Test 21 --- Checking tailCone -TEST /// -P = intersection(matrix {{1,0},{-1,0},{0,1}},matrix {{1},{2},{3}}); -C = posHull matrix {{0},{-1}}; -assert(tailCone P == C) -P = intersection (matrix{{2,1,1},{1,2,1},{1,1,2}},matrix{{2},{2},{2}}); -C = posHull matrix{{1,1,-3},{1,-3,1},{-3,1,1}}; -assert(tailCone P == C) -/// - --- Test 22 --- Checking smallestFace for polyhedra -TEST /// -P = convexHull matrix {{1,1,1,1,-1,-1,-1,-1},{1,1,-1,-1,1,1,-1,-1},{1,-1,1,-1,1,-1,1,-1}}; -F1 = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1},{1,1,1,1}}; -F2 = convexHull matrix {{1,1},{1,1},{-1,1}}; -assert(smallestFace(matrix{{0},{0},{0}},P) == P) -assert(smallestFace(matrix{{1/2},{1/3},{1}},P) == F1) -assert(smallestFace(matrix{{1},{1},{3/4}},P) == F2) -/// - --- Test 23 --- Checking smallestFace for cones -TEST /// -C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -F1 = posHull matrix {{1,0},{0,1},{0,0}}; -F2 = posHull matrix {{0},{0},{1}}; -assert(smallestFace(matrix{{1},{2},{3}},C) == C) -assert(smallestFace(matrix{{2},{3},{0}},C) == F1) -assert(smallestFace(matrix{{0},{0},{5}},C) == F2) -/// - --- Test 24 --- Checking inInterior for polyhedra and cones -TEST /// -P = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1}}; -assert not inInterior(matrix{{2},{1}},P) -assert not inInterior(matrix{{1},{0}},P) -assert inInterior(matrix{{0},{0}},P) -C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -assert not inInterior(matrix{{0},{0},{0}},C) -assert not inInterior(matrix{{-1},{0},{0}},C) -assert inInterior(matrix{{1},{2},{3}},C) -/// - --- Test 25 --- Checking interiorPoint -TEST /// -P = convexHull matrix {{1,-1,0,0},{0,0,1,-1}}; -p = matrix {{0_QQ},{0}}; -assert(interiorPoint P == p) -/// - --- Test 26 --- Checking interiorVector -TEST /// -C = posHull matrix {{1,2,3},{2,3,1},{3,1,2}}; -p = matrix {{1_QQ},{1},{1}}; -assert(interiorVector C == p) -/// - --- Test 27 --- Checking commonFace for polyhedra -TEST /// -P1 = convexHull matrix {{1,1,1,1,-1},{1,1,-1,-1,0},{1,-1,1,-1,0}}; -P2 = intersection (matrix {{-1,0,0},{0,1,0},{0,-1,0},{0,0,1}},matrix {{-1},{1},{1},{1}}); -assert not commonFace(P1,P2) -P2 = intersection {P2,(matrix {{0,0,-1}},matrix {{1}})}; -assert commonFace(P1,P2) -/// - --- Test 28 --- Checking commonFace for cones -TEST /// -C1 = posHull matrix {{1,2},{2,1}}; -C2 = posHull matrix {{1,1},{1,0}}; -assert not commonFace(C1,C2) -C1 = posHull matrix {{1,1},{2,1}}; -assert commonFace(C1,C2) -/// - --- Test 29 --- Checking areCompatible -TEST /// -C1 = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -C2 = posHull matrix {{1,1,0},{1,0,1},{0,-1,-1}}; -assert not (areCompatible(C1,C2))#0 -C2 = posHull {matrix {{1,0},{0,1},{0,0}}, C2}; -assert (areCompatible(C1,C2))#0 -/// - --- Test 30 --- Checking makeFan and Fan basics -TEST /// -C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -F = makeFan C; -assert(F#"generatingCones" === set {C}) -assert(F#"ambient dimension" == 3) -assert(F#"top dimension of the cones" == 3) -assert(F#"number of generating cones" == 1) -assert not F#"isComplete" -/// - --- Test 31 --- Checking makeFan and addCone -TEST /// -C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -C1 = posHull matrix {{1,0,0},{0,-1,0},{0,0,1}}; -C2 = posHull matrix {{-1,0,0},{0,1,0},{0,0,1}}; -C3 = posHull matrix {{1,0,0},{0,1,0},{0,0,-1}}; -F = makeFan {C,C1,C2,C3}; -assert(F#"generatingCones" === set {C,C1,C2,C3}) -assert(F#"ambient dimension" == 3) -assert(F#"number of generating cones" == 4) -assert(F#"isPure") -L = set {posHull matrix {{1,0},{0,-1},{0,0}},posHull matrix {{0,0},{0,-1},{1,0}},posHull matrix {{-1,0},{0,1},{0,0}},posHull matrix {{-1,0},{0,0},{0,1}},posHull matrix {{1,0},{0,0},{0,-1}},posHull matrix {{0,0},{1,0},{0,-1}}}; -assert(L === F#"faces") -L = set {matrix {{1_QQ},{0},{0}},matrix {{-1_QQ},{0},{0}},matrix {{0_QQ},{1},{0}},matrix {{0_QQ},{-1},{0}},matrix {{0_QQ},{0},{1}},matrix {{0_QQ},{0},{-1}}}; -assert(L === F#"rays") -C = posHull matrix {{-1,0},{0,1},{0,0}}; -F1 = addCone(C,F); -assert(F == F1) -/// - --- Test 32 --- Checking makeFan, skeleton, isComplete, isPure, addCone, isProjective -TEST /// -C = posHull matrix {{1,0,0},{0,1,0},{0,0,1}}; -C1 = posHull matrix {{1,0,0},{0,-1,0},{0,0,1}}; -C2 = posHull matrix {{-1,0,0},{0,1,0},{0,0,1}}; -C3 = posHull matrix {{1,0,0},{0,1,0},{0,0,-1}}; -F = makeFan {C,C1,C2,C3}; -L = {posHull matrix {{1,0},{0,-1},{0,0}},posHull matrix {{0,0},{0,-1},{1,0}},posHull matrix {{-1,0},{0,1},{0,0}},posHull matrix {{-1,0},{0,0},{0,1}},posHull matrix {{1,0},{0,0},{0,-1}},posHull matrix {{0,0},{1,0},{0,-1}},posHull matrix {{1,0},{0,1},{0,0}},posHull matrix {{1,0},{0,0},{0,1}},posHull matrix {{0,0},{1,0},{0,1}}}; -assert(set L === set cones(2,F)) -F1 = makeFan {posHull matrix {{1},{0},{0}},posHull matrix {{-1},{0},{0}},posHull matrix {{0},{1},{0}},posHull matrix {{0},{-1},{0}},posHull matrix {{0},{0},{1}},posHull matrix {{0},{0},{-1}}}; -assert(skeleton(1,F) == F1) -assert not isComplete F -assert isPure F -C = posHull matrix {{-1,0,0},{0,-1,0},{0,0,-1}}; -C1 = posHull matrix {{-1,0,0},{0,1,0},{0,0,-1}}; -C2 = posHull matrix {{1,0,0},{0,-1,0},{0,0,-1}}; -C3 = posHull matrix {{-1,0,0},{0,-1,0},{0,0,1}}; -F = addCone({C,C1,C2,C3},F); -assert(F#"number of generating cones" == 8) -assert isPure F -assert isComplete F -assert isSmooth F -P = isProjective F; -assert(normalFan P == F) -/// - --- Test 33 --- Checking isSmooth and smoothSubfan -TEST /// -C1 = posHull matrix {{1,2},{2,1}}; -C2 = posHull matrix {{1,0},{2,1}}; -C3 = posHull matrix {{1,2},{0,1}}; -F = makeFan {C1,C2,C3}; -assert not isSmooth F -F1 = makeFan {C2,C3}; -assert(smoothSubfan F == F1) -/// - --- Test 34 --- Checking normalFan -TEST /// -P = convexHull matrix {{1,0,0},{0,1,0}}; -F = normalFan P; -L = {posHull matrix {{1,0},{0,1}},posHull matrix {{1,-1},{0,-1}},posHull matrix {{0,-1},{1,-1}}}; -assert(F == makeFan L) -P = convexHull (matrix {{1,0,0},{0,1,0}},matrix {{1},{1}}); -F = normalFan P; -L = {posHull matrix {{1,0},{0,1}},posHull matrix {{1,1},{0,-1}},posHull matrix {{0,-1},{1,1}}}; -assert(F == makeFan L) -/// - --- Test 35 ---Checking ccRefinement -TEST /// -M = matrix {{1,-1,0,0},{0,0,1,-1},{1,1,1,1}}; -F = ccRefinement M; -F1 = makeFan {posHull matrix {{1,0,0},{0,1,0},{1,1,1}},posHull matrix {{-1,0,0},{0,1,0},{1,1,1}},posHull matrix {{-1,0,0},{0,-1,0},{1,1,1}},posHull matrix {{1,0,0},{0,-1,0},{1,1,1}}}; -assert(F == F1) -/// - --- Test 36 --- Checking imageFan -TEST /// -C = posHull matrix {{1,1,-1,-1},{1,-1,1,-1},{1,1,1,1}}; -F = imageFan(matrix {{1,0,0},{0,1,0}},C); -F1 = makeFan {posHull matrix {{1,1},{1,-1}},posHull matrix {{1,-1},{1,1}},posHull matrix {{-1,-1},{1,-1}},posHull matrix {{1,-1},{-1,-1}}}; -assert(F == F1) -F = imageFan(matrix {{1,2,0},{0,0,1}},C); -F1 = makeFan {posHull matrix {{-3,-1},{1,1}},posHull matrix {{-1,1},{1,1}},posHull matrix {{1,3},{1,1}}}; -assert(F == F1) -/// - --- Test 37 --- Checking hilbertBasis -TEST /// -C = posHull matrix {{1,2},{2,1}}; -H = hilbertBasis C; -L = {matrix {{1},{1}},matrix {{2},{1}},matrix {{1},{2}}}; -assert(set H === set L) -C = posHull matrix {{1,1,0},{0,3,0},{0,0,1}}; -H = hilbertBasis C; -L = {matrix {{1},{0},{0}},matrix {{1},{1},{0}},matrix {{1},{2},{0}},matrix {{1},{3},{0}},matrix {{0},{0},{1}}}; -assert(set H === set L) -/// - --- Test 38 --- Checking latticePoints -TEST /// -P = convexHull matrix {{1,-1,0,0},{0,0,1,-1}}; -LP = latticePoints P; -LP1 = {matrix {{1},{0}},matrix {{-1},{0}},matrix {{0},{1}},matrix {{0},{-1}},matrix {{0},{0}}}; -assert(set LP === set LP1) -P = intersection(matrix {{-6,0,0},{0,-6,0},{0,0,-6},{1,1,1}},matrix{{-1},{-1},{-1},{1}}); -assert(latticePoints P == {}) -/// - --- Test 39 --- Checking minkowskiSum -TEST /// -P1 = convexHull matrix {{1,0,0},{0,1,0}}; -P2 = convexHull matrix {{-1,0,0},{0,-1,0}}; -P1 = minkowskiSum(P1,P2); -P2 = convexHull matrix {{1,1,0,0,-1,-1},{-1,0,-1,1,0,1}}; -assert(P1 == P2) -P1 = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1},{0,0,0,0}}; -P2 = convexHull matrix {{0,0},{0,0},{1,-1}}; -P1 = minkowskiSum(P1,P2); -P2 = convexHull matrix {{1,1,1,1,-1,-1,-1,-1},{1,1,-1,-1,1,1,-1,-1},{1,-1,1,-1,1,-1,1,-1}}; -assert(P1 == P2) -/// - --- Test 40 --- Checking directProduct -TEST /// -P1 = convexHull matrix {{1,-1}}; -P2 = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1}}; -P1 = directProduct(P1,P2); -P2 = convexHull matrix {{1,1,1,1,-1,-1,-1,-1},{1,1,-1,-1,1,1,-1,-1},{1,-1,1,-1,1,-1,1,-1}}; -assert(P1 == P2) -C1 = posHull matrix {{1,2},{2,1}}; -C2 = posHull matrix {{1,0},{0,1}}; -C1 = directProduct(C1,C2); -C2 = posHull matrix {{1,2,0,0},{2,1,0,0},{0,0,1,0},{0,0,0,1}}; -assert(C1 == C2) -F1 = normalFan hypercube 1; -F2 = normalFan hypercube 2; -F3 = normalFan hypercube 3; -assert(F3 == directProduct(F1,F2)) -/// - --- Test 41 --- Checking affineImage for polyhedra -TEST /// -P = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1}}; -A = matrix {{1,2},{3,4}}; -v = matrix {{-1},{1}}; -P = affineImage(A,P,v); -Q = convexHull matrix {{2,-2,0,-4},{8,0,2,-6}}; -assert(P == Q) -P = intersection(matrix{{-1,0,0},{0,-1,0},{0,0,-1}},matrix{{1},{1},{1}}); -A = matrix {{0,2,0},{1,0,1},{0,0,2}}; -v = matrix {{1},{1},{1}}; -P = affineImage(A,P,v); -Q = convexHull(matrix{{-1},{-1},{-1}},matrix{{0,2,0},{1,0,1},{0,0,2}}); -assert(P == Q) -/// - --- Test 42 --- Checking affineImage for cones -TEST /// -C = posHull matrix {{1,1,2},{1,2,1},{2,1,1}}; -A = matrix {{1,-1,0},{0,1,-1},{-1,0,1}}; -C = affineImage(A,C); -C1 = posHull matrix {{0,-1,1},{-1,1,0},{1,0,-1}}; -assert(C == C1) -/// - --- Test 43 --- Checking affinePreimage for polyhedra -TEST /// -P = convexHull matrix {{1,1,-1,-1},{1,-1,1,-1}}; -A = matrix {{1,2},{3,4}}; -v = matrix {{-1},{1}}; -P = affinePreimage(A,P,v); -Q = convexHull matrix {{0,-2,-4,-6},{0,1,3,4}}; -assert(P == Q) -P = intersection(matrix{{-1,0,0},{0,-1,0},{0,0,-1}},matrix{{1},{1},{1}}); -A = matrix {{0,2,0},{1,0,1},{0,0,2}}; -v = matrix {{1},{1},{1}}; -P = affinePreimage(A,P,v); -Q = convexHull(matrix{{-1},{-1},{-1}},matrix{{1,0,-1},{0,1,0},{0,0,1}}); -assert(P == Q) -/// - --- Test 44 --- Checking affinePreimage for cones -TEST /// -C = posHull matrix {{1,1,2},{1,2,1},{2,1,1}}; -A = matrix {{1,-1,0},{0,1,-1},{-1,0,0}}; -C = affinePreimage(A,C); -C1 = posHull matrix {{-2,-1,-1},{-3,-3,-2},{-4,-4,-4}}; -assert(C == C1) -/// - --- Test 45 --- Checking pyramid -TEST /// -P = intersection(matrix {{1,0},{-1,0},{0,1},{0,-1}},matrix {{1},{1},{1},{1}}); -P = pyramid P; -Q = convexHull matrix {{1,1,-1,-1,0},{1,-1,1,-1,0},{0,0,0,0,1}}; -assert(P == Q) -/// - --- Test 46 --- Checking crossPolytope -TEST /// -P = crossPolytope(3,2); -Q = convexHull matrix {{2,-2,0,0,0,0},{0,0,2,-2,0,0},{0,0,0,0,2,-2}}; -assert(P == Q) -/// - --- Test 47 --- Checking cyclicPolytope -TEST /// -P = cyclicPolytope(3,5); -Q = convexHull matrix {{0,1,2,3,4},{0,1,4,9,16},{0,1,8,27,64}}; -assert(P == Q) -/// - --- Test 48 --- Checking emptyPolyhedron -TEST /// -P = emptyPolyhedron 2; -assert(dim P == -1) -assert(ambDim P == 2) -/// - --- Test 49 --- Checking hypercube -TEST /// -P = hypercube (3,3); -Q = convexHull matrix {{3,3,3,3,-3,-3,-3,-3},{3,3,-3,-3,3,3,-3,-3},{3,-3,3,-3,3,-3,3,-3}}; -assert(P == Q) -/// - --- Test 50 --- Checking hirzebruch -TEST /// -F = hirzebruch 3; -F1 = makeFan {posHull matrix{{1,0},{0,1}},posHull matrix{{1,0},{0,-1}},posHull matrix{{0,-1},{1,3}},posHull matrix{{0,-1},{-1,3}}}; -assert(F == F1) -/// - --- Test 51 --- Checking newtonPolytope -TEST /// -R = QQ[a,b,c]; -f = a^2*b+b^3*c^2+c^4*a^3+a*b*c+a^5*c^6; -P =newtonPolytope f; -Q = convexHull matrix {{2,0,3,1,5},{1,3,0,1,0},{0,2,4,1,6}}; -assert(P == Q) -/// - --- Test 52 --- Checking posOrthant -TEST /// -C1 = posOrthant 3; -C2 = intersection matrix {{1,0,0},{0,1,0},{0,0,1}}; -assert(C1 == C2) -/// - --- Test 53 --- Checking statePolytope -TEST /// -R = QQ[a,b,c]; -I = ideal(a^2-b,a*b-c); -(L,P) = statePolytope I; -Q = convexHull matrix {{21,3,1,1,6,2},{0,9,7,4,0,2},{0,0,2,4,5,5}}; -L1 = { {{b^2,a*b,a^2}}, {{b^3,a*c,a*b,a^2}}, {{a^3,b}}, {{c^2,a*c,a*b,a^2}}, {{c,b}}, {{c,a^2}}}; -L = apply(L,entries); -assert(P == Q) -assert(set L === set L1) -/// - --- Test 54 --- Checking stdSimplex -TEST /// -P = stdSimplex 2; -Q = intersection(matrix{{-1,0,0},{0,-1,0},{0,0,-1}},matrix{{0},{0},{0}},matrix{{1,1,1}},matrix{{1}}); -assert(P == Q) -/// - --- Test 55 --- Checking equality of polyhedral objects -TEST /// -L1 = set {posOrthant 3, hypercube 2, crossPolytope 4, hirzebruch 5}; -L2 = set {hirzebruch 5, posOrthant 3, hypercube 2, crossPolytope 4}; -assert(L1 === L2) -/// - --- Test 56 --- Checking vertexEdgeMatrix and vertexFacetMatrix -TEST /// -P = convexHull matrix {{0,-1,1,-1,1},{0,-1,-1,1,1},{-1,1,1,1,1}}; -M = matrix {{0,1,2,3,4,5,6,7,8},{1,1,1,0,1,1,0,0,0},{2,1,0,1,0,0,0,1,0},{3,0,0,0,1,0,1,1,0},{4,0,1,1,0,0,0,0,1},{5,0,0,0,0,1,1,0,1}}; -N = matrix {{0,1,2,3,4,5},{1,1,1,1,1,0},{2,1,0,1,0,1},{3,0,1,1,0,1},{4,1,0,0,1,1},{5,0,1,0,1,1}}; -assert(vertexEdgeMatrix P == M) -assert(vertexFacetMatrix P == N) -/// - --- Test 57 --- Checking minFace and maxFace -TEST /// -P = hypercube 3; -w = matrix {{1},{2},{1}}; -F1 = convexHull matrix {{1},{1},{1}}; -F2 = convexHull matrix {{-1},{-1},{-1}}; -assert(F1 == maxFace(w,P)) -assert(F2 == minFace(w,P)) -C = posHull matrix {{2,-1,1},{-1,1,1},{0,-1,1}}; -C1 = posHull matrix {{-1,2},{1,-1},{-1,0}}; -assert(C1 == minFace(w,C)) -/// - --- Test 58 --- Checking proximum -TEST /// -P = crossPolytope 3; -p = matrix {{1},{2},{3}}; -q = matrix {{0_QQ},{1},{0}}; -assert(q == proximum(p,P)) -p = matrix {{1},{1/2},{1}}; -q = matrix {{1/2},{0},{1/2}}; -assert(q == proximum(p,P)) -P = convexHull map(QQ^3,QQ^3,1); -p = matrix {{2},{2},{0}}; -q = matrix {{1/2},{1/2},{0}}; -assert(q == proximum(p,P)) -/// - --- Test 59 --- Checking triangulate -TEST /// -P = crossPolytope 3; -L = triangulate P; -L = apply(L,convexHull); -L1 = {convexHull{matrix{{1_QQ},{0},{0}},matrix{{0_QQ},{1},{0}},matrix{{0_QQ},{0},{1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{-1_QQ},{0},{0}},matrix{{0_QQ},{1},{0}},matrix{{0_QQ},{0},{1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{1_QQ},{0},{0}},matrix{{0_QQ},{-1},{0}},matrix{{0_QQ},{0},{1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{1_QQ},{0},{0}},matrix{{0_QQ},{1},{0}},matrix{{0_QQ},{0},{-1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{-1_QQ},{0},{0}},matrix{{0_QQ},{-1},{0}},matrix{{0_QQ},{0},{1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{-1_QQ},{0},{0}},matrix{{0_QQ},{1},{0}},matrix{{0_QQ},{0},{-1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{1_QQ},{0},{0}},matrix{{0_QQ},{-1},{0}},matrix{{0_QQ},{0},{-1}},matrix{{0_QQ},{0},{0}}}, - convexHull{matrix{{-1_QQ},{0},{0}},matrix{{0_QQ},{-1},{0}},matrix{{0_QQ},{0},{-1}},matrix{{0_QQ},{0},{0}}}}; -assert(set L === set L1) -/// - --- Test 60 --- Checking volume -TEST /// -P = hypercube 3; -assert(volume P == 8) -P = crossPolytope 3; -assert(volume P == 4/3) -/// - --- Test 61 --- Checking incompCones -TEST /// -L = {posHull matrix{{1,0},{1,1}},posHull matrix{{1,0},{0,-1}},posHull matrix{{-1,0},{0,1}},posHull matrix{{1,1},{0,1}},posHull matrix {{1,2},{2,1}}}; -assert(incompCones L == {(L#0,L#4),(L#3,L#4)}) -L = L_{0..3}|{hirzebruch 3}; -assert(incompCones L == {(L#0,L#4),(L#2,L#4),(L#3,L#4)}) -assert(incompCones(L#2,L#4) == {(L#2,posHull matrix {{0,-1},{-1,3}}),(L#2,posHull matrix {{0,-1},{1,3}})}) -L = {posHull matrix {{-1,0},{0,1}},posHull matrix {{-1,0},{0,-1}},posHull matrix {{0,-1},{-1,3}},posHull matrix {{0,-1},{1,3}}}; -L = {(L#0,L#2),(L#0,L#3),(L#1,L#2)}; -assert(set incompCones(normalFan hypercube 2,hirzebruch 3) === set L) -/// - --- Test 62 --- Checking isNormal for Cones -TEST /// -P = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0},{1,1,3}}; -Q = hypercube 2; -assert not isNormal P -assert isNormal Q -/// - --- Test 63 --- Checking sublatticeBasis and toSublattice -TEST /// -assert(sublatticeBasis matrix{{2,4,2,4},{1,2,2,3}} == matrix {{2,2},{1,2}}) -assert(sublatticeBasis convexHull matrix {{1,2,2},{0,-1,2}} == matrix {{-1,1},{1,0}}) -assert(toSublattice convexHull matrix {{2,0},{0,3}} == convexHull matrix {{0,1}}) -/// - --- Test 64 --- Checking Scaling -TEST /// -assert(3/2 * hypercube(2,2) == hypercube(2,3)) -/// - --- Test 65 --- Checking ehrhart -TEST /// -P = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0},{0,1,0}}; -assert(ehrhart P == (1/2)*x^2+(3/2)*x+1) -/// - -end