newPackage(
	"MonomialAlgebras",
    	Version => "2.3",
    	Date => "May 11, 2013",
    	Authors => {
         {Name => "David Eisenbud", Email => "de@msri.org", HomePage => "http://www.msri.org/~de/"},
         {Name => "Janko Boehm", Email => "boehm@mathematik.uni-kl.de", HomePage => "http://www.mathematik.uni-kl.de/~boehm/"},
         {Name => "Max Nitsche", Email => "nitsche@mis.mpg.de", HomePage => ""}
         },
    	Headline => "monomial algebras",
	Keywords => {"Commutative Algebra"},
	Certification => {
	     "journal name" => "The Journal of Software for Algebra and Geometry",
	     "journal URI" => "http://j-sag.org/",
	     "article title" => "Decomposition of Monomial Algebras: Applications and Algorithms",
	     "acceptance date" => "2013-04-07",
	     "published article URI" => "https://msp.org/jsag/2013/5-1/p02.xhtml",
	     "published code URI" => "https://msp.org/jsag/2013/5-1/jsag-v5-n1-x02-code.zip",
	     "repository code URI" => "http://github.com/Macaulay2/M2/blob/master/M2/Macaulay2/packages/MonomialAlgebras.m2",
	     "release at publication" => "68f41d641fadb0a1054023432eb60177f1d7cbd9",
	     "version at publication" => "2.3",
	     "volume number" => "5",
	     "volume URI" => "http://j-sag.org/Volume5/"
	     },
	CacheExampleOutput => false,
     	PackageExports => { "Polyhedra" },
	AuxiliaryFiles => true,
    	DebuggingMode => false,
        --PackageExports => {"Polyhedra","FourTiTwo"},
        Configuration => {"Use4ti2"=>false}
        )

-- For information see documentation key "MonomialAlgebras" below.


-*
Copyright (C) [2013] [David Eisenbud, Janko Boehm, Max Nitsche]

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
*-


export {"monomialAlgebra", "MonomialAlgebra", "binomialIdeal", "affineAlgebra","randomMonomialAlgebra","findMonomialSubalgebra",
       "decomposeMonomialAlgebra","decomposeHomogeneousMA",
       "findGeneratorsOfSubalgebra",
       "isCohenMacaulayMA","isGorensteinMA","isBuchsbaumMA","isSeminormalMA","isNormalMA","isSimplicialMA",
       "homogenizeSemigroup","adjoinPurePowers",
       "codimMA","degreeMA","regularityMA",
       "CoefficientField","ReturnMingens",
       "randomSemigroup","Num","SetSeed","Simplicial","Decomposition"}

if version#"VERSION" < "1.4" then error "This package was written for Macaulay2 Version 1.4 or higher.";

-- this is problematic, because the "configuration" mechanism is intended for the end user:
needsPackage("FourTiTwo",Configuration=>{"keep files" => false})

--------------------------------------------------------------------------
MonomialAlgebra = new Type of MutableHashTable

MonomialAlgebra.synonym = "MonomialAlgebra"
MonomialAlgebra#{Standard,AfterPrint} = M -> (
      << endl;
      << concatenate(interpreterDepth:"o") << lineNumber << " : "
      << "MonomialAlgebra generated by "|toString(degrees(ring M))
      << endl;)

monomialAlgebra=method(Options=>{CoefficientField=>ZZ/101})
monomialAlgebra List := opt -> B->(
    if #B!=0 and class first B ===ZZ then (
      B = adjoinPurePowers homogenizeSemigroup apply(B,j->{j});
    );
    K:=opt.CoefficientField;
    x:=symbol x;
    R:=K[x_0..x_(#B-1),Degrees=>B];
monomialAlgebra R)

net MonomialAlgebra := M -> net ring M

monomialAlgebra PolynomialRing := opt -> R ->(
new MonomialAlgebra from {symbol ring => R})

ring MonomialAlgebra:= M -> M.ring

degrees MonomialAlgebra := M -> degrees ring M




---------------------------------------------------------------------------------
-- the associated binomial ideal of a semigroup algebra
-- R should be a multigraded poly ring
-- forms the ideal in R corresponding to the degree monoid algebra
-- generated by monomials x^(B_i), where B is the list of degrees of
-- the variables of R

binomialIdeal=method(Options=>{CoefficientField=>ZZ/101})
binomialIdeal PolynomialRing := opt-> R -> (
  B:=degrees R;
  if ((options MonomialAlgebras).Configuration)#"Use4ti2" then (
     tg:=toricGroebner(transpose matrix B);
     J:=toBinomial(tg,R)
  ) else (
     m := #B_0;
     t := local t;
     k:= coefficientRing R;
     T := k[t_0..t_(m-1)];
     targ :=  apply(B, b -> product(apply (#b, i-> t_i^(b_i))));
     J=ideal mingens ker map(T,R,targ)
  );
J)

binomialIdeal MonomialAlgebra := opt -> M-> binomialIdeal ring M

binomialIdeal List := opt-> B -> (
binomialIdeal monomialAlgebra(B,opt))



----------------------------------------------------------------------------------------
-- the monomial algebra associated to a multigraded poly ring

affineAlgebra=method(Options=>{CoefficientField=>ZZ/101})

affineAlgebra PolynomialRing := opt-> R -> (
I:=binomialIdeal R;
R/I)

affineAlgebra List := opt-> B -> (
I:=binomialIdeal B;
(ring I)/I)

affineAlgebra MonomialAlgebra := opt -> M-> affineAlgebra ring M


----------------------------------------------------------------------------------------
-- general decomposition algorithm

decomposeMonomialAlgebra=method(Options=>{Verbose=>0,ReturnMingens=>false,CoefficientField=>ZZ/101})
decomposeMonomialAlgebra RingMap := opt-> f -> (
  vb:=opt.Verbose;
  S:=target f;
  P:=source f;
  K:= coefficientRing S;
  p := numgens P;
  n := numgens S;
  B := degrees S;
  C := degrees P;
  c := sum C;
  m := #B_0;
  I := binomialIdeal S;
                if vb>0 then (
                 <<(net(coefficientRing(ring I))|"["|net(B)|"]  =  "|net(K)|"["|net(gens(S))|"]  /  "|net(I));
                 << endl;
                 <<("The image of the variables of the source");
                 << endl;
                );
  fP:=f(ideal vars P);
                if vb>0 then (
                 <<(fP);
                );
  N := S^1/(fP+I);
                if vb>0 then (
                 << endl;
                 <<(net(K)|" - basis of "|net(K)|"["|net(gens(S))|"] / "|net(mingens(fP+I)));
                 << endl;
                 << basis N;
                 << endl;
                 << "Degrees of the basis elements";
                 << endl;
                 << last degrees basis N;
                 << endl;
                );
  bN := last degrees basis N;
  if opt.ReturnMingens then return({f,bN});
  Cm := transpose matrix C;
  C1 := gens gb Cm;
                if vb>0 then (
                 << "The degrees of the source variables";
                 << endl;
                 <<(Cm);
                 << endl;
                 << "Minimal generators of the finitely generated abelian group generated by the degrees of the source";
                 << endl;
                 << C1;
                );
  L := partition(j->(transpose matrix {j})%C1,bN);
                if vb>0 then (
                 << endl;
                 << "Equivalence classes of the degrees of the basis of the quotient modulo the degrees of the source";
                 << endl;
                 << L;
                );
  IA:=binomialIdeal P;
  PIA:=P/IA;
  dc:=applyPairs (L, (k,V0)->(
                     if vb>0 then (
                      << "------------------------------------------------------------------------------------";
                      << endl;
                      << ("The reduced representative "|net(k)|" in  image "|(net B)|"  /  image "|(net C));
                      << "represents the equivalence class of basis vectors";
                      << endl;
                      << V0;
                      << endl;
                      << "---------------------------------------------";
                      << endl;
                     );
     V:=apply(V0, v1->(entries transpose((transpose matrix {v1})-k))#0);
                     if vb>0 then (
                      << "Differences of the elements of the equivalence class to the chosen representative";
                      << endl;
                      << V;
                     );
     vm := transpose matrix V;
                     if vb>0 then (
                      << endl;
                      << "Write the differences in terms of the generators of the degree monoid of the source";
                     );
     coef := vm//Cm;
     coef = coef%(gens ker Cm);
                     if vb>0 then (
                      << endl;
                      <<((net vm)|" = "|net(Cm)|" * "|(net coef));
                     );
     mins := transpose matrix {for i from 0 to numrows coef -1 list
            min (entries coef^{i})#0};
                     if vb>0 then (
                      << endl;
                      << "Minimum of each row";
                      << endl;
                      << mins;
                      << endl;
                      << "Representative + Generators * Minima = Twist";
                      << endl;
                     );
     twist:=k+Cm*mins;
                     if vb>0 then (
                      <<(net(k)|" + "|net(Cm)|" * "|net(mins)|" = "|net(twist));
                     );
     Mins := mins * matrix{{numcols vm:1}};
                     if vb>0 then (
                      << endl;
                      << "Subtract minima from each column of the coefficients";
                     );
     coef1 := coef-Mins;
                     if vb>0 then (
                      << endl;
                      << coef1;
                      << endl;
                      << "Form the corresponding monomial ideal generated by the columns";
                     );
     gamma:=ideal(apply(numcols coef1,
		  v->product(apply(p, j->P_j^(coef1_v_j)))));
                     if vb>0 then (
                      << endl;
                      << gamma;
                      << endl;
                      <<("The submodule Gamma_"|net(k)|" of "|net(coefficientRing(ring I))|"["|net(B)|"] is (written multiplicatively)");
                      t := local t;
                      T := K[t_0..t_(m-1)];
                      targ :=  apply(C, c -> product(apply (#c, i-> t_i^(c_i))));
                      slist:=apply(#(gens P),j->P_j=>targ#j);
                      << endl;
                      <<(net(product(apply (m, i-> Power(T_i,twist_(i,0)))))|" * "|net(sub(gamma,slist)));
                      << endl;
                      <<("which is isomorphic to the ideal of "|(net PIA));
                      << endl;
                      <<(net(sub(gamma,PIA))|" twisted by "|net(twist));
                      << endl;
                     );
     (k,{sub(gamma,PIA), twist})
  )))



decomposeMonomialAlgebra PolynomialRing :=opt-> R ->(
  S:=findMonomialSubalgebra R;
  f:=map(R,S);
  decomposeMonomialAlgebra(f,opt))

decomposeMonomialAlgebra MonomialAlgebra :=opt -> M -> decomposeMonomialAlgebra(ring M,opt)


decomposeMonomialAlgebra List := opt-> B -> (
  decomposeMonomialAlgebra(monomialAlgebra(B,CoefficientField=>opt.CoefficientField),opt));


homogenizeSemigroup=method()
homogenizeSemigroup List := A ->(
     d := max (A/sum);
     A/(a->append(a, d-sum a))
     )

adjoinPurePowers=method()
adjoinPurePowers List := B -> (
     d :=  sum B_0;
     m := #(B_0);
     unique(apply(m, i-> apply(m, j -> if(j == i) then d else 0)) | B)
     )



----------------------------------------------------------------------------------------
-- decomposition algorithm in the homogeneous case with ZZ-twists


decomposeHomogeneousMA=method(Options=>{Verbose=>0,ReturnMingens=>false,CoefficientField=>ZZ/101})
decomposeHomogeneousMA RingMap := opt-> f -> (
  l:=findLinearForm degrees source f;
  dc:=decomposeMonomialAlgebra(f,opt);
  dc=applyValues(dc,j->{j#0,(transpose(l)*j#1)_(0,0)};
  RA:=ring first first values dc;
  I:=ideal RA;
  K:=coefficientRing RA;
  PRA0:=K[gens RA];
  RA0:=PRA0/sub(I,PRA0);
  applyValues(dc,j->{sub(j#0,RA0),j#1})))

decomposeHomogeneousMA PolynomialRing := opt-> R -> (
  l:=findLinearForm degrees R;
  dc:=decomposeMonomialAlgebra(R,opt);
  dc=applyValues(dc,j->{j#0,(transpose(l)*j#1)_(0,0)});
  RA:=ring first first values dc;
  I:=ideal RA;
  K:=coefficientRing RA;
  PRA0:=K[gens RA];
  RA0:=PRA0/sub(I,PRA0);
  applyValues(dc,j->{sub(j#0,RA0),j#1}))

decomposeHomogeneousMA List := opt-> B -> (
  if #B!=0 and class first B ===ZZ then (
    B = adjoinPurePowers homogenizeSemigroup apply(B,j->{j});
  );
  l:=findLinearForm B;
  c:=(transpose l)*(B#0);
  dc:=decomposeMonomialAlgebra(B,opt);
  dc=applyValues(dc,j->{j#0,(transpose(l)*j#1)_(0,0)});
  RA:=ring first first values dc;
  I:=ideal RA;
  K:=coefficientRing RA;
  PRA0:=K[gens RA];
  RA0:=PRA0/sub(I,PRA0);
  applyValues(dc,j->{sub(j#0,RA0),j#1}))

decomposeHomogeneousMA MonomialAlgebra := opt -> M -> decomposeHomogeneousMA(ring M,opt)

-- find a linear form with constant value on B
findLinearForm=method()
findLinearForm List := B ->(
  Li:=gens ker matrix apply(B,j->prepend(1,j));
  sv:=first entries Li^{0};
  nzc:=select(#sv,j->(sv#j)!=0);
  if #nzc==0 then error("Input not homogeneous");
  si:=first nzc;
  l:=(Li_{si})^{1..(-1+rank target Li)};
  a:=-Li_(0,si);
  (1/a)*sub(l,QQ));




decomposeMonomialAlgebra(List,List) := opt-> (B,A) -> (
  x:=symbol x;
  K :=opt.CoefficientField;
  R:=K[x_0..x_(#B-1),Degrees=>B];
  v:=apply(A,j->x_(P:=positions(B,jj->j==jj); if #P!=1 then error "expected second argument to be a subset of the first" else P#0));
  S:=K[v,Degrees=>A];
  f:=map(R,S);
  decomposeMonomialAlgebra(f,opt));


---------------------------------------------------------------------------------
-- tests for ring theoretic properties (simplicial case)
---------------------------------------------------------------------------------
-- Gorenstein


isGorensteinMA=method()

isGorensteinMA List := B ->(
  isGorensteinMA monomialAlgebra B)


isGorensteinMA PolynomialRing := S ->(
  if not isSimplicialMA S then error("Expected simplicial monomial algebra");
  dc:=values decomposeMonomialAlgebra S;
  Ilist:=first\dc;
  R:=ring first Ilist;
  hlist:=first\entries\transpose\last\dc;
  -- test for CM
  if not all(Ilist,j->j==ideal(1_R)) then return(false);
  shlist:=sum\hlist;
  msum:=max shlist;
  if #select(shlist,j->j==msum)>1 then return(false);
  i:=maxPosition(shlist);
  maxel:=hlist#i;
  j0:=0;j1:=0;
  while #hlist>0 do (
    for j0 from 0 to -1+#hlist do (
     j1=position(hlist,jj->jj==maxel-hlist#j0);
     if j1=!=null then break;
    );
    if j1===null then return(false);
    hlist=rem(hlist,set {j0,j1});
  );
  true);

isGorensteinMA MonomialAlgebra := M -> isGorensteinMA ring M

rem=method()
rem(List,Set):=(L,I)->(
  while #I>0 do (
    m:=max(toList I);
    L=drop(L,{m,m});
    I=I - set {m};
  );
  L)

TEST ///
debug MonomialAlgebras
assert(#(rem({10,11,12,13,14,15,16,17},set {3,4,1}))==5)
///

---------------------------------------------------------------------------------
-- Buchsbaum


isBuchsbaumMA=method()

isBuchsbaumMA List := B ->(
  isBuchsbaumMA monomialAlgebra B)


isBuchsbaumMA PolynomialRing := S ->(
  if not isSimplicialMA S then error("Expected simplicial monomial algebra");
  dc:=values decomposeMonomialAlgebra S;
  Ilist:=first\dc;
  R:=ring first Ilist;
  if not all(Ilist,j->((j==ideal(1_R)) or (j==ideal(vars R)))) then return(false);
  hlist:=first\entries\transpose\last\dc;
  dcmax:=select(dc,j->ideal(vars R)==first j);
  hmax:=first\entries\transpose\last\dcmax;
  B:=degrees S;
  A:=first\findGeneratorsOfSubalgebra B;
  BminusA:=select(B,j->not member(j,A));
  hb:=join toSequence apply(hmax,j->apply(BminusA,jj->jj+j));
  hbh:=select(hb,j->member(j,hlist));
  Ih:=select(dc,j->member(first entries transpose last j,hbh));
  all(first\Ih,j->j==ideal(1_R)));

isBuchsbaumMA MonomialAlgebra := M -> isBuchsbaumMA ring M


---------------------------------------------------------------------------------
-- Cohen-Macaulay

isCohenMacaulayMA=method()

isCohenMacaulayMA MonomialAlgebra := M -> isCohenMacaulayMA ring M

isCohenMacaulayMA List := B ->(
  isCohenMacaulayMA monomialAlgebra B)

isCohenMacaulayMA PolynomialRing := R ->(
  if not isSimplicialMA R then error("Expected simplicial monomial algebra");
  dc:=first\(values decomposeMonomialAlgebra R);
  S:=ring first dc;
  all(dc,j->j==ideal(1_S)));


---------------------------------------------------------------------------------
-- tests for seminormal and normal


isSeminormalMA=method()

isSeminormalMA List := B ->(
  isSeminormalMA monomialAlgebra B)


isSeminormalMA PolynomialRing := R ->(
  if not isSimplicialMA R then error("Expected simplicial monomial algebra");
  fBA:=decomposeMonomialAlgebra(R,ReturnMingens=>true);
  f:=fBA#0;BA:=fBA#1;
  A:=transpose matrix degrees source f;
  co:=entries((sub(A,QQ))^-1 * transpose matrix BA);
  max(max\co)<=1)

isSeminormalMA MonomialAlgebra := M -> isSeminormalMA ring M

isNormalMA=method()

isNormalMA List := B ->(
  isNormalMA monomialAlgebra B)


isNormalMA PolynomialRing := R ->(
  if not isSimplicialMA R then error("Expected simplicial monomial algebra");
  fBA:=decomposeMonomialAlgebra(R,ReturnMingens=>true);
  f:=fBA#0;BA:=fBA#1;
  A:=transpose matrix degrees source f;
  co:=entries((sub(A,QQ))^-1 * transpose matrix BA);
  max(max\co)<1)

isNormalMA MonomialAlgebra := M -> isNormalMA ring M



---------------------------------------------------------------------------------
-- test simplicial


isSimplicialMA=method()
isSimplicialMA List := B ->(
  A:=first\(findGeneratorsOfSubalgebra B);
  P:=posHull transpose matrix B;
  d:=dim P;
  #A==d)

isSimplicialMA PolynomialRing :=R->(
  isSimplicialMA degrees R)

isSimplicialMA MonomialAlgebra := M -> isSimplicialMA ring M


---------------------------------------------------------------------------------
-- test homogeneous

testHomogeneous=method()
testHomogeneous PolynomialRing :=R->(
  #(unique(sum\(degrees R)))<=1)


---------------------------------------------------------------------------------
-- find generators of the subalgebra associated to the positive hull

findGeneratorsOfSubalgebra=method()
findGeneratorsOfSubalgebra List := B ->(
  P:=posHull transpose matrix B;
  d:=dim P;
  embdim:=ambDim P;
  if (numColumns linealitySpace P)>0 then error("expected cone without lineality space");
  L:=entries transpose rays(P);
  apply(L,v->findGenerator(B,v)));

findGenerator=method()
  findGenerator(List,List):=(B,v)->(
  L:=select(#B,j->1==rank matrix {B#j,v});
  --if #L>1 then error("dependent generators");
  i:=minPosition apply(L,j->sum(B#j));
  i1:=L#i;
  {B#i1,i1})


findMonomialSubalgebra=method()
findMonomialSubalgebra PolynomialRing := R -> (
  K:= coefficientRing R;
  B := degrees R;
  L:=findGeneratorsOfSubalgebra B;
  A:=apply(L,first);
  subV:=apply(L,j-> R_(last j));
  K[toSequence subV,Degrees=>A])

findMonomialSubalgebra MonomialAlgebra := M -> (
  monomialAlgebra findMonomialSubalgebra ring M
)
---------------------------------------------------------------------------------
-- computing the regularity via the decomposition

regularityMA=method(Options=>{CoefficientField=>ZZ/101,Decomposition=>hashTable {}})
  regularityMA List :=opt->B->(
  if opt.Decomposition===hashTable {} then (
    regularityMA monomialAlgebra(B,CoefficientField=>opt.CoefficientField)
  ) else (
    regularityMAdc(opt.Decomposition,B)
  )
)

regularityMA PolynomialRing :=opt->R->(
  B:=degrees R;
  --if not isSimplicialMA R then error("Expected simplicial monomial algebra");
  --if not testHomogeneous R then error("Expected homogeneous monomial algebra");
  dc:=opt.Decomposition;
  if dc===hashTable {} then dc=decomposeMonomialAlgebra R;
  if #(first B)==2 then return(regularityMonomialCurve(dc,B));
  regularityMAdc(dc,B))

regularityMA MonomialAlgebra := opt -> M -> regularityMA(ring M,opt)


regularityMAdc=method()
regularityMAdc(HashTable,List):=(dc,B)->(
  L:=values(dc);
  I1:=first first L;
  Z:=ring I1;
  P:=ring ideal Z;
  Li:=gens ker matrix apply(B,j->prepend(1,j));
  sv:=first entries Li^{0};
  nzc:=select(#sv,j->(sv#j)!=0);
  if #nzc==0 then error("Input not homogeneous");
  si:=first nzc;
  l:=(Li_{si})^{1..(-1+rank target Li)};
  a:=-Li_(0,si);
  K:=coefficientRing P;
  P1:=K[gens P];
  KA:=coker sub(matrix entries gens sub(ideal Z,P1),P1);
  L1:={};
  for j from 0 to #L-1 do (
    I1=first(L#j);
    matg:=matrix entries sub(gens I1,P1);
    g:=map(KA,source matg,matg);
    reg:=regularity image g;
    shift:=(((matrix entries transpose last(L#j))*l)_(0,0))/a;
    L1=append(L1,{reg,shift});
  );
  L2:=apply(L1,j->j#0+j#1);
  m:=max(L2);
  L3:=apply(#L,j->(L#j,L2#j));
  {m,apply(select(L3,j->j#1==m),first)})


-- special case of monomial curves

regularityMonomialCurve=method()
regularityMonomialCurve(HashTable,List):=(dc,B)->(
  L:=values(dc);
  I1:=first first L;
  Z:=ring I1;
  P:=ring ideal Z;
  Li:=gens ker matrix apply(B,j->prepend(1,j));
  if Li==0 then error("Input not homogeneous");
  l:=Li^{1..(-1+rank target Li)};
  a:=-Li_(0,0);
  if a==0 or rank source Li>1 then error("C(A) is not a cone of full dimension");
  K:=coefficientRing P;
  L1:={};
  for j from 0 to #L-1 do (
    I1=first(L#j);
    R:=K[gens ring I1,MonomialOrder=>Lex];
    --reg:=regularity sub(I1,R);
    shift:=(((matrix entries transpose last(L#j))*l)_(0,0))/a;
    expo:=exponents sum first entries mingens sub(I1,R);
    if #expo==1 then (
       reg:=0;
    ) else (
       reg=-1 + max apply(-1+#expo, j->expo#j#0+expo#(j+1)#1);
       --<<(expo,shift);
    );
    L1=append(L1,{reg,shift});
  );
  L2:=apply(L1,j->j#0+j#1);
  m:=max(L2);
  L3:=apply(#L,j->(L#j,L2#j));
  {m,apply(select(L3,j->j#1==m),first)})


---------------------------------------------------------------------------------
-- codimension of a monomial algebra
codimMA=method()
codimMA List := B ->(
  P:=posHull transpose matrix B;
  d:=dim P;
  --embdim:=P#"ambient dimension";
  #B-d)

codimMA PolynomialRing := R ->(
  codimMA degrees R)

codimMA MonomialAlgebra := M -> codimMA ring M


---------------------------------------------------------------------------------
-- degree of a monomial algebra (also non-simplicial case)
degreeMA=method(Options=>{Verbose=>0})

-- is independent of K
degreeMA List :=opt-> B ->(
  K:=ZZ/2;
  x:=symbol x;
  R:=K[x_0..x_(#B-1),Degrees=>B];
  degreeMA R)


degreeMA PolynomialRing :=opt-> R ->(
  K:= coefficientRing R;
  B := degrees R;
  L:=findGeneratorsOfSubalgebra B;
  A:=first\L;
  subV:=apply(L,j-> R_(last j));
  S:=K[toSequence subV,Degrees=>A];
  f:=map(R,S);
  dc:=decomposeMonomialAlgebra(f);
  R1:=K[toSequence gens R];
  S1:=K[toSequence subV];
  degS:=degree sub(binomialIdeal S,S1);
         if opt.Verbose>4 then (
             degR:=degree sub(binomialIdeal R,R1);
             <<("Degree monomial algebra ideal B "|net(degR));
             <<("Degree monomial algebra ideal A "|net(degS));
             <<("Number of components "|net(#(values dc)));
             if (#(values dc))*degS != degR then error("Degree computation is wrong");
        );
  (#(values dc))*degS)


degreeMA MonomialAlgebra := opt -> M -> degreeMA(ring M,opt)



---------------------------------------------------------------------------------
-- generate a random semigroup

randomSemigroup=method(Options=>{SetSeed=>false,Simplicial=>false,Num=>1})
randomSemigroup(ZZ,ZZ,ZZ):=opt->(a,d,c)->(
  if opt.SetSeed===true then setRandomSeed();
  if class(opt.SetSeed)===ZZ then setRandomSeed(opt.SetSeed);
  t:=symbol t;
  R:=ZZ/2[t_0..t_(d-1)];
  IB:=(ideal vars R)^a;
  E0:=first\exponents\(first entries mingens IB);
  A:=entries(a*id_(ZZ^d));
  E:=toList(set(E0)-set(A));
  L:=toList apply(opt.Num, n->(
   if opt.Simplicial then (
     B:=A;
     while #B<c+d do (
       j:=random(#E);
       if #E==0 then error("Codimension too large");
       B=append(B,E#j);
       E=drop(E,{j,j});
     );
   ) else (
     dPB:=-1;
     while dPB!=d do (
       E:=E0;
       B={};
       while #B<c+d do (
         j=random(#E);
         if #E==0 then error("Codimension too large");
         B=append(B,E#j);
         E=drop(E,{j,j});
       );
       PB:=posHull transpose matrix B;
       dPB=dim PB;
     );
   );
   B));
  if opt.Num==1 then L#0 else L);


randomMonomialAlgebra=method(Options=>{SetSeed=>false,Simplicial=>false,Num=>1})
randomMonomialAlgebra(ZZ,ZZ,ZZ):=opt->(a,d,c)->(
if opt.Num==1 then (
   monomialAlgebra randomSemigroup(a,d,c,opt)
) else (
   monomialAlgebra \ randomSemigroup(a,d,c,opt)
))

------------------------------------------------------------------------------------------



beginDocumentation()


--generateAssertions

TEST ///

     kk=ZZ/101
     B = {{1,2},{3,0},{0,4},{0,5}}
     S = kk[x_0..x_3, Degrees=> B]
assert( binomialIdeal S == ideal(x_0^3*x_2-x_1*x_3^2, x_0^6-x_1^2*x_2^3, x_1*x_2^4-x_0^3*x_3^2, x_2^5-x_3^4) )

///

TEST ///
     kk=ZZ/101
     B = {{1,2},{3,0},{0,4},{0,5}}
     I=ideal affineAlgebra B;
     R=ring I;
     J=ideal(R_0^3*R_2-R_1*R_3^2,R_0^6-R_1^2*R_2^3,R_1*R_2^4-R_0^3*R_3^2,R_2^5-R_3^4);
assert( I== J)
///

TEST///
B={{5,0},{4,1},{1,4},{0,5}};
A={{5,0},{0,5}};
dc=decomposeMonomialAlgebra(B,A);
assert(#dc == 5)
///

TEST///
dc=decomposeMonomialAlgebra({1,4,5});
R=ring first first values dc;
r=new HashTable from {matrix {{-1}, {1}} => {ideal(1_R), matrix {{4}, {1}}},
                      matrix {{-2}, {2}} => {ideal(R_1^2,R_0), matrix {{3}, {2}}},
                      matrix {{0},{0}} =>   {ideal(1_R), matrix {{0}, {0}}},
                      matrix {{1}, {-1}} => {ideal(1_R), matrix{{1}, {4}}},
                      matrix {{2}, {-2}} => {ideal(R_1,R_0^2), matrix {{2}, {3}}}};
assert(dc === r)
///



TEST///
dc=values decomposeHomogeneousMA({{5,0},{4,1},{1,4},{0,5}});
R=ring first first dc;
r=set {{ideal(1_R), 1_QQ},
                      {ideal(R_0^2,R_1), 1_QQ},
                      {ideal(1_R), 0_QQ},
                      {ideal(1_R), 1_QQ},
                      {ideal(R_0,R_1^2), 1_QQ}};
assert((set dc) === r)
///



TEST///
A = {{1,2},{3,0},{0,4},{0,5}}
assert(homogenizeSemigroup A =={{1, 2, 2}, {3, 0, 2}, {0, 4, 1}, {0, 5, 0}})
///

TEST///
A = {{1,4}, {2,3}}
assert(adjoinPurePowers A == {{5, 0}, {0, 5}, {1, 4}, {2, 3}})
///

TEST///
     a=3
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
assert(     isCohenMacaulayMA B )
assert(     isCohenMacaulayMA R )
     B={{4, 0}, {0, 4}, {1, 3}, {3, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
assert( not     isCohenMacaulayMA B)
assert( not     isCohenMacaulayMA R)
///

TEST///
     B={{2, 0}, {0, 2}, {1, 1}}
     R=QQ[x_0..x_2,Degrees=>B]
     assert(isGorensteinMA B)
     assert(isGorensteinMA R)
///

TEST///
     B={{3, 0}, {0, 3}, {1, 2}, {2, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
assert( not     isGorensteinMA R)
     R=QQ[x_0..x_4,Degrees=>{{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}]
assert(     isGorensteinMA R)
///

TEST///
     B={{6,0},{0,6},{4,2},{1,5}}
     R=QQ[x_0..x_3,Degrees=>B]
assert( not     isBuchsbaumMA B)
assert( not     isBuchsbaumMA R)
     R=QQ[x_0..x_3,Degrees=>{{4,0},{0,4},{3,1},{1,3}}]
assert(     isBuchsbaumMA R)
///

TEST///
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     R=QQ[x_0..x_4,Degrees=>B]
assert(     isSeminormalMA R)
assert(not     isNormalMA R)
assert(     isSeminormalMA B)
assert(not     isNormalMA B)
///

TEST///
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     R=QQ[x_0..x_4,Degrees=>B]
assert(     isSimplicialMA R)
assert(     isSimplicialMA B)
///


TEST///
     a=4
     B={{a, 0}, {2, a-2}, {1, a-1}, {a-1, 1}}
     assert(findGeneratorsOfSubalgebra B ==  {{{4, 0}, 0}, {{1, 3}, 2}})
///

TEST///
     a=4
     B={{a, 0}, {2, a-2}, {1, a-1}, {a-1, 1}}
     M=monomialAlgebra B
     assert(degrees findMonomialSubalgebra M ==  {{4, 0}, {1, 3}})
///


TEST///
     a=5
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_1..x_(#B),Degrees=>B]
     assert( first regularityMA(B) == 3)
     assert( first regularityMA(R) == 3)
///


TEST ///
     B={{2, 2, 1}, {1, 1, 3}, {1, 2, 2}, {2, 0, 3}, {1, 4, 0}, {2, 3, 0}, {1, 3, 1}}
     R=QQ[x_1..x_(#B),Degrees=>B]
    assert( degreeMA R == 6)
    assert( degreeMA B == 6)
///


TEST ///
     B={{2, 2, 1}, {1, 1, 3}, {1, 2, 2}, {2, 0, 3}, {1, 4, 0}, {2, 3, 0}, {1, 3, 1}}
     R=QQ[x_1..x_(#B),Degrees=>B]
     assert(codimMA R == 4)
     assert(codimMA B == 4)
///

TEST ///
      setRandomSeed();
      L=randomSemigroup(5,3,7,Num=>2)
      assert(L== {{{5, 0, 0}, {1, 3, 1}, {1, 4, 0}, {0, 2, 3}, {3, 0, 2}, {0, 1, 4}, {0, 5, 0}, {4, 1, 0}, {2,
0, 3}, {4, 0, 1}}, {{1, 3, 1}, {1, 4, 0}, {2, 3, 0}, {0, 5, 0}, {1, 2, 2}, {3, 1, 1}, {0, 0,
5}, {1, 1, 3}, {4, 0, 1}, {0, 2, 3}}})
///

TEST ///
      setRandomSeed();
      L=degrees \ randomMonomialAlgebra(5,3,7,Num=>2)
    assert(L== {{{5, 0, 0}, {1, 3, 1}, {1, 4, 0}, {0, 2, 3}, {3, 0, 2}, {0, 1, 4}, {0, 5, 0}, {4, 1, 0}, {2,
0, 3}, {4, 0, 1}}, {{1, 3, 1}, {1, 4, 0}, {2, 3, 0}, {0, 5, 0}, {1, 2, 2}, {3, 1, 1}, {0, 0,
5}, {1, 1, 3}, {4, 0, 1}, {0, 2, 3}}})
///


doc ///
  Key
    MonomialAlgebras
  Headline
    Decompose a monomial algebra as a module over a subalgebra.
  Description
    Text
      {\bf Overview:}

      Consider a monoid B in \mathbb{N}^m and a submonoid A \subseteq B (both finitely generated)
      such that K[B] is a finitely generated K[A]-module (with the module structure
      given by inclusion, and K being a field).

      Note that this is equivalent to the condition that the corresponding cones C(A) and C(B)
      spanned by the monoids are equal. From this it follows that G(B)/G(A) is finite, where
      G(A) and G(B) are the groups generated by the monoids.

      This package provides functions to decompose the corresponding monomial algebra K[B] as a
      direct sum of monomial ideals in K[A]. In

      Le Tuan Hoa, Juergen Stueckrad: Castelnuovo-Mumford regularity of simplicial toric rings,
      Journal of Algebra, Volume 259, Issue 1, 1 January 2003, pages 127-146,

      it is shown that this decomposition exists in the case that B is homogeneous and simplicial
      and A is generated by minimal generators of B on the extremal rays of C(B). In particular
      then K[A] is a Noether normalization of K[B].

      For the existence of the decomposition in the general (non-simplicial) case, and for algorithms
      computing the decomposition and the regularity see:

      J. Boehm, D. Eisenbud, M. Nitsche: Decomposition of semigroup algebras, Exper. Math. 21(4) (2012) 385-394, @HREF"http://arxiv.org/abs/1110.3653"@.

      Using the decomposition algorithm, the package also provides fast functions to test ring-theoretic
      properties of monomial algebras. For details on the corresponding algorithms see:

      J. Boehm, D. Eisenbud, M. Nitsche: Decomposition of Monomial Algebras: Applications and Algorithms, 2012, @HREF"http://arxiv.org/abs/1206.1735"@.


      {\bf Key user functions:}

      {\it Decomposition:}

      @TO decomposeMonomialAlgebra@ -- Decomposition of one monomial algebra over a subalgebra.

      @TO decomposeHomogeneousMA@ -- Decomposition of one homogeneous monomial algebra over a subalgebra.

      {\it Ring-theoretic properties:}

      @TO isCohenMacaulayMA@ -- Test whether a simplicial monomial algebra is Cohen-Macaulay.

      @TO isGorensteinMA@ -- Test whether a simplicial monomial algebra is Gorenstein.

      @TO isBuchsbaumMA@ -- Test whether a simplicial monomial algebra is Buchsbaum.

      @TO isNormalMA@ -- Test whether a simplicial monomial algebra is normal.

      @TO isSeminormalMA@ -- Test whether a simplicial monomial algebra is seminormal.

      @TO isSimplicialMA@ -- Test whether a monomial algebra is simplicial.

      {\it Regularity:}

      @TO regularityMA@ -- Compute the regularity via the decomposition.

      @TO degreeMA@ -- Compute the degree via the decomposition.

      @TO codimMA@ -- Compute the codimension of a monomial algebra.


      {\bf Options:}

      Computation of the binomial ideal associated to B via the function @TO binomialIdeal@
      can be done via two different methods:

      The standard method uses the Macaulay2 function @TO ker@ and requires no configuration.

      Alternatively, the external program 4ti2, @HREF"http://www.4ti2.de/"@ can be called, which is delivered with the Macaulay2 distribution.
      For large examples this is typically much faster. To use this option
      load the {\it MonomialAlgebras} package with the following configuration option:

      @TO loadPackage@("MonomialAlgebras",Configuration=>\{"Use4ti2"=>true\})

      Note that you can change the standard option by editing the file init-MonomialAlgebras.m2 in the .Macaulay directory in your home directory.

      In order to use 4ti2, on some systems you may have to configure the Macaulay2 package {\it FourTiTwo} first.


      {\bf Setup:}

      Install this @TO Package@ by doing

      @TO installPackage@("MonomialAlgebras")

      {\bf Tests:}

      The following files contain the tuples (regularity, degree, codim) for every semigroup B in \mathbb{N}^d with fixed {\bf d} and fixed coordinate sum {\bf a}.
      Using this data we have verified the Eisenbud-Goto conjecture in these cases.

      {\bf d = 3:}

      a = 3:    @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebras/proveEG_33.m2","proveEG_33"}@

      a = 4:    @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebras/proveEG_43.m2","proveEG_43"}@

      a = 5:    @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebras/proveEG_53.zip","proveEG_53"}@

      {\bf d = 4:}

      a = 2:    @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebras/proveEG_24.m2","proveEG_24"}@

      a = 3:    @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebras/proveEG_34.zip","proveEG_34"}@

      {\bf d = 5:}

      a = 2:    @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebras/proveEG_25.zip","proveEG_25"}@

      More functions related to testing the Eisenbud-Goto conjecture can be found in the
      @HREF{"http://www.math.uni-sb.de/ag/schreyer/jb/Macaulay2/MonomialAlgebrasExtras/html","MonomialAlgebraExtras"}@ package.

      {\bf Diagrams:}

      We illustrate the tests with @TO "Diagrams"@ showing projections of the set of all possible (regularity, degree, codim).
///

diagramsDoc = ///
  Key
    "Diagrams"
  Headline
    Diagrams illustrating the tests
  Description
   Text
    For fixed a and d the following diagrams show all possible

    regularity +  codim against degree

    degree - regularity against codim

    degree - codim against regularity

    codim against regularity for semigroups with regularity - degree + codim = 0

    regularity on top of codim against degree.


    The line corresponds to the Eisenbud-Goto bound.


      {\bf d = 3:}

      a = 3:

      @IMG{"src" => "IMGDIRprojr_33.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojc_33.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojd_33.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGplane_33.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGbar_33.jpg", "alt" => ""}@

      a = 4:

      @IMG{"src" => "IMGDIRprojr_43.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojc_43.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojd_43.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGplane_43.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGbar_43.jpg", "alt" => ""}@

      a = 5:

      @IMG{"src" => "IMGDIRprojr_53.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojc_53.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojd_53.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGplane_53.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGbar_53.jpg", "alt" => ""}@

      {\bf d = 4:}

      a = 2:

      @IMG{"src" => "IMGDIRprojr_24.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojc_24.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojd_24.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGplane_24.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGbar_24.jpg", "alt" => ""}@

      a = 3:

      @IMG{"src" => "IMGDIRprojr_34.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojc_34.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojd_34.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGplane_34.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGbar_34.jpg", "alt" => ""}@


      {\bf d = 5:}

      a = 2:

      @IMG{"src" => "IMGDIRprojr_25.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojc_25.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIRprojd_25.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGplane_25.jpg", "alt" => ""}@

      @IMG{"src" => "IMGDIREGbar_25.jpg", "alt" => ""}@



///

doc replace("IMGDIR", replace("PKG", "MonomialAlgebras",
		currentLayout#"package"), diagramsDoc)

doc ///
  Key
    MonomialAlgebra
  Headline
   The class of all monomialAlgebras.
  Description
   Text
     The class of monomial algebras K[B] where B is a subsemigroup of \mathbb{N}^r.

     You can create a monomial algebra via the function @TO monomialAlgebra@ by either specifying

     - the semigroup B as a list of generators. The field K is selected via the option @TO CoefficientField@.

     - a list of positive integers which is converted by @TO adjoinPurePowers@ and @TO homogenizeSemigroup@
       into a list B of elements of \mathbb{N}^2. The field K is selected via the option @TO CoefficientField@.

     - a multigraded polynomial ring K[X] with @TO Degrees@ R = B.

     This data can be extracted as follows:

     @TO (ring, MonomialAlgebra)@ returns the associated multigraded polynomial ring.

     @TO (degrees,MonomialAlgebra)@ returns B.

      {\bf Key functions:}

      {\it Decomposition:}

      @TO decomposeMonomialAlgebra@ -- Decomposition of a monomial algebra over the subalgebra corresponding to the convex hull of the degree monoid.

      @TO decomposeHomogeneousMA@ -- Decomposition of a homogeneous monomial algebra over the subalgebra corresponding to the convex hull of the degree monoid.

      {\it Ring-theoretic properties:}

      @TO isCohenMacaulayMA@ -- Test whether a simplicial monomial algebra is Cohen-Macaulay.

      @TO isGorensteinMA@ -- Test whether a simplicial monomial algebra is Gorenstein.

      @TO isBuchsbaumMA@ -- Test whether a simplicial monomial algebra is Buchsbaum.

      @TO isNormalMA@ -- Test whether a simplicial monomial algebra is normal.

      @TO isSeminormalMA@ -- Test whether a simplicial monomial algebra is seminormal.

      @TO isSimplicialMA@ -- Test whether a monomial algebra is simplicial.

      {\it Regularity:}

      @TO regularityMA@ -- Compute the regularity via the decomposition.

      @TO degreeMA@ -- Compute the degree via the decomposition.

      @TO codimMA@ -- Compute the codimension of a monomial algebra.


 ///


doc ///
  Key
    monomialAlgebra
    (monomialAlgebra, List)
    (monomialAlgebra, PolynomialRing)
  Headline
    Create a monomial algebra
  Usage
    monomialAlgebra R
    monomialAlgebra B
  Inputs
    R  : PolynomialRing
           multigraded, with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B  : List
           In the case B is specified, K is set via the @TO Option@ @TO CoefficientField@.
           If a list of positive integers is given, the function uses @TO adjoinPurePowers@ and @TO homogenizeSemigroup@
           to convert it into a list of elements of \mathbb{N}^2.
  Outputs
    :MonomialAlgebra
  Description
   Text
     Create a monomial algebra K[B] by either specifying

     - the semigroup B as a list of generators. The field K is selected via the option @TO CoefficientField@.

     - a list of positive integers which is converted by @TO adjoinPurePowers@ and @TO homogenizeSemigroup@
       into a list B of elements of \mathbb{N}^2. The field K is selected via the option @TO CoefficientField@.

     - a multigraded polynomial ring R with @TO Degrees@ R = B.


     Specifying B:

   Example
     B = {{1,2},{3,0},{0,4},{0,5}}
     monomialAlgebra B
     monomialAlgebra(B, CoefficientField=>QQ)

   Text

    Specifying R:

   Example
     kk=ZZ/101
     B = {{1,2},{3,0},{0,4},{0,5}}
     monomialAlgebra(kk[x_0..x_3, Degrees=> B])

   Text

    Specifying a list of integers to define a monomial curve:

   Example
     M = monomialAlgebra {1,4,8,9,11}

///



doc ///
  Key
    (degrees, MonomialAlgebra)
  Headline
    Generators of the degree monoid
  Usage
    degrees M
  Inputs
    M  : MonomialAlgebra
  Outputs
    :List
  Description
   Text
      Returns the generators of the degree monoid of M.

   Example
     M = monomialAlgebra {1,4,8,9,11}
     degrees M
///


doc ///
  Key
    (ring, MonomialAlgebra)
  Headline
    Multigraded polynomial ring associated to a monomial algebra
  Usage
    ring M
  Inputs
    M  : MonomialAlgebra
  Outputs
    :Ring
  Description
   Text
      Returns the multigraded polynomial ring associated to M.

   Example
     M = monomialAlgebra {1,4,8,9,11}
     ring M
     degrees ring M
///

doc ///
  Key
    (net, MonomialAlgebra)
  Headline
    Pretty print for monomial algebras
  Usage
    net M
  Inputs
    M  : MonomialAlgebra
  Outputs
    :Net
  Description
   Text
      Pretty print for monomial algebras. Prints the associated polynomial ring of M.

   Example
     M = monomialAlgebra {1,4,8,9,11}
     net M
///



doc ///
  Key
    binomialIdeal
    (binomialIdeal, PolynomialRing)
    (binomialIdeal, List)
    (binomialIdeal, MonomialAlgebra)
  Headline
    Compute the ideal of a monomial algebra
  Usage
    binomialIdeal P
    binomialIdeal B
    binomialIdeal M
  Inputs
    P: PolynomialRing
           multigraded, with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B  : List
           In the case B is specified, K is set via the @TO Option@ @TO CoefficientField@.
    M  : MonomialAlgebra
  Outputs
    :Ideal
  Description
   Text
      Returns the toric ideal associated to the degree monoid B of the polynomial ring P
      as an ideal of P.

   Example
     kk=ZZ/101
     B = {{1,2},{3,0},{0,4},{0,5}}
     S = kk[x_0..x_3, Degrees=> B]
     binomialIdeal S
     C = {{1,2},{0,5}}
     P = kk[y_0,y_1, Degrees=> C]
     binomialIdeal P
     M = monomialAlgebra B
     binomialIdeal M
///


doc ///
  Key
    affineAlgebra
    (affineAlgebra, PolynomialRing)
    (affineAlgebra, List)
    (affineAlgebra, MonomialAlgebra)
  Headline
    Define a monomial algebra
  Usage
    affineAlgebra P
    affineAlgebra B
  Inputs
    P: PolynomialRing
           multigraded, with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B  : List
           In the case B is specified, K is set via the @TO Option@ @TO CoefficientField@.
  Outputs
    :Ring
  Description
   Text
      Returns the monomial algebra K[B]=P/@TO binomialIdeal@(P) associated to the degree monoid of the polynomial ring P.

   Example
     kk=ZZ/101
     B = {{1,2},{3,0},{0,4},{0,5}}
     S = kk[x_0..x_3, Degrees=> B]
     affineAlgebra S
     affineAlgebra B
     M = monomialAlgebra B
     affineAlgebra M
///




doc ///
  Key
    decomposeMonomialAlgebra
    (decomposeMonomialAlgebra,RingMap)
    (decomposeMonomialAlgebra,PolynomialRing)
    (decomposeMonomialAlgebra,List)
    (decomposeMonomialAlgebra,List,List)
    (decomposeMonomialAlgebra,MonomialAlgebra)
  Headline
    Decomposition of one monomial algebra over a subalgebra
  Usage
    decomposeMonomialAlgebra f
    decomposeMonomialAlgebra R
    decomposeMonomialAlgebra B
    decomposeMonomialAlgebra(B,A)
    decomposeMonomialAlgebra M
  Inputs
    f : RingMap
        between multigraded polynomial rings, or
    R  : PolynomialRing
           multigraded, with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B  : List
           In the case B is specified, K is set via the @TO Option@ @TO CoefficientField@.
           If a list of positive integers is given, the function uses @TO adjoinPurePowers@ and @TO homogenizeSemigroup@
           to convert it into a list of elements of \mathbb{N}^2.
    A  : List
           of elements of B, such that K[B] is finite as a K[A]-module. If A is specified, the function chooses the canonical map f from the A-graded to the B-graded polynomial ring.
    M  : MonomialAlgebra
  Outputs
    :HashTable
       with the following data: Let B be the degree monoid of the @TO target@ of f and analogously A for the @TO source@.
       The @TO keys@ are representatives of congruence classes in G(B) / G(A).
       The value associated to a key k is a tuple whose first component is an ideal of
       K[A] isomorphic to the K[A]-submodule of K[B] consisting of elements in the class k,
       and whose second component is an element of G(B) that is the translation
       vector between the weights of the generators of the ideal and those of the submodule of
       K[B].

  Description
   Text

     Let K[B] be the monomial algebra of the degree monoid of the @TO target@ of f and
     analogously K[A] for @TO source@ of f. Assume that K[B] is finite as a K[A]-module.

     The monomial algebra K[B] is decomposed as a direct sum of monomial ideals in K[A] with twists in G(B).

     If R with degrees B is specified then A is computed via @TO findGeneratorsOfSubalgebra@.

     Note that the shift chosen by the function depends on the monomial ordering of K[A] (in the non-simplicial case).

   Example
      B = {{4,2},{10,6},{3,7},{3,6}}
      A = {{4,2},{10,6},{3,7}}
      S = ZZ/101[x_0..x_(#B-1), Degrees=>B];
      P = ZZ/101[x_0..x_(#A-1), Degrees=>A];
      f = map(S,P)
      decomposeMonomialAlgebra f
   Text

      Decomposition over a polynomial ring
   Example
      B = {{4,2},{3,7},{10,6},{3,6}}
      A = {{4,2},{3,7}}
      S = ZZ/101[x_0..x_(#B-1), Degrees=>B];
      P = ZZ/101[x_0..x_(#A-1), Degrees=>A];
      f = map(S,P)
      decomposeMonomialAlgebra f
   Text

      Specifying R:
   Example
      B = {{4,2},{10,6},{3,7},{3,6}}
      S = ZZ/101[x_0..x_(#B-1), Degrees=>B];
      decomposeMonomialAlgebra S
   Text

      Specifying a monomial algebra:
   Example
      M = monomialAlgebra {{4,2},{10,6},{3,7},{3,6}}
      decomposeMonomialAlgebra M
   Text

      Specifying a monomial curve by a list of positive integers:
   Example
      decomposeMonomialAlgebra {1,4,8,9,11}
   Text

      Some simpler examples:
   Example
      B = adjoinPurePowers homogenizeSemigroup {{1,2},{3,0},{0,4},{0,5}}
      A = adjoinPurePowers homogenizeSemigroup {{0,5}}
      S = ZZ/101[x_0..x_(#B-1), Degrees=>B];
      P = ZZ/101[x_0..x_(#A-1), Degrees=>A];
      f = map(S,P)
      decomposeMonomialAlgebra f
   Text

    Consider the family of smooth monomial curves in $\mathbb{P}^3$, the one of degree $d$
    having parametrization
    $$
     (s,t) \rightarrow (s^d, s^{d-1}t, st^{d-1} t^d) \in \mathbb{P}^3.
    $$

   Example
     kk=ZZ/101;
     L= for d from 4 to 10 list (f= map(kk[x_0..x_3,Degrees=>{{d,0},{d-1,1},{1,d-1},{0,d}}], kk[x_0,x_3,Degrees=>{{d,0},{0,d}}]));
     print\decomposeMonomialAlgebra\L
   Text

     See also @TO decomposeHomogeneousMA@:

   Example
     decomposeHomogeneousMA {{2,0,1},{0,2,1},{1,1,1},{2,2,1},{2,1,1},{1,4,1}}
///


doc ///
  Key
    decomposeHomogeneousMA
    (decomposeHomogeneousMA,RingMap)
    (decomposeHomogeneousMA,PolynomialRing)
    (decomposeHomogeneousMA,List)
    (decomposeHomogeneousMA,MonomialAlgebra)
  Headline
    Decomposition of one monomial algebra over a subalgebra
  Usage
    decomposeHomogeneousMA f
    decomposeHomogeneousMA R
    decomposeHomogeneousMA B
    decomposeHomogeneousMA M
  Inputs
    f : RingMap
        between multigraded polynomial rings such that the degree monoids are homogeneous
        and the degrees are minimal generating sets of the degree monoids, or
    R  : PolynomialRing
           multigraded, with homogeneous degree monoid, such that B = @TO degrees@ R are minimal generators of the degree monoid,
           and set K = @TO coefficientRing@ R, or
    B  : List
           with the generators of an affine semigroup in \mathbb{N}^d.
           In the case B is specified, K is set via the @TO Option@ @TO CoefficientField@.
           If a list of positive integers is given, the function uses @TO adjoinPurePowers@ and @TO homogenizeSemigroup@
           to convert it into a list of elements of \mathbb{N}^2.
    M  : MonomialAlgebra
  Outputs
    :HashTable
       with the following data: Let B be the degree monoid of the @TO target@ of f and analogously A for the @TO source@.
       The @TO keys@ are representatives of congruence classes in G(B) / G(A).
       The value associated to a key k is a tuple whose first component is a monomial ideal of
       K[A] isomorphic to the K[A]-submodule of K[B] consisting of elements in the class k,
       and whose second component is an element of @TO ZZ@ that is the twist between
       the ideal and the submodule of K[B] with respect to the standard grading (which gives the minimal generators degree 1).

  Description
   Text

     Let K[B] be the monomial algebra of the degree monoid of the @TO target@ of f and
     let analogously K[A] for @TO source@ of f. Assume that K[B] is finite as a K[A]-module.

     The monomial algebra K[B] is decomposed as a direct sum of monomial ideals in K[A] with twists in ZZ.

     If B or R with degrees B is specified then A is computed via @TO findGeneratorsOfSubalgebra@.

     Note that the shift chosen by the function depends on the monomial ordering of K[A] (in the non-simplicial case).

   Example
      B = {{4,0},{3,1},{1,3},{0,4}}
      S = ZZ/101[x_0..x_(#B-1), Degrees=>B];
      decomposeHomogeneousMA S
      decomposeHomogeneousMA B
   Text

   Example
       decomposeHomogeneousMA {{2,0,1},{0,2,1},{1,1,1},{2,2,1},{2,1,1},{1,4,1}}
   Text

   Example
       M = monomialAlgebra {{2,0,1},{0,2,1},{1,1,1},{2,2,1},{2,1,1},{1,4,1}}
       decomposeHomogeneousMA M
///



doc ///
  Key
    homogenizeSemigroup
    (homogenizeSemigroup,List)
  Headline
    Homogenize generators of a semigroup.
  Usage
    homogenizeSemigroup(A)
  Inputs
    A:List
        of lists of integers
  Outputs
    :List
  Description
   Text
      Homogenize the generators of a semigroup adding an additional coordinate.
   Example
      A = {{1,2},{3,0},{0,4},{0,5}}
      homogenizeSemigroup A
///



doc ///
  Key
    adjoinPurePowers
    (adjoinPurePowers, List)
  Headline
    adjoin semigroup elements corresponding to pure powers of variables
  Usage
    adjoinPurePowers A
  Inputs
    A:List
        of lists of ZZ, containing generators of A, all of the same degree d.
  Outputs
    :List
        of lists of ZZ. Same as A, but with elements of the form (d,0...), (0,d,0...)...
	prepended.
  Description
   Text
      Used to simplify the input of complicated homogeneous monoids.
   Example
      A = {{1,4}, {2,3}}
      adjoinPurePowers A
///



doc ///
  Key
    CoefficientField
    [decomposeMonomialAlgebra,CoefficientField]
    [decomposeHomogeneousMA,CoefficientField]
    [regularityMA,CoefficientField]
    [binomialIdeal,CoefficientField]
    [affineAlgebra,CoefficientField]
    [monomialAlgebra,CoefficientField]
  Headline
    Option to set the coefficient field.
  Description
   Text
    This option can be used to set the coefficient field of the polynomial rings
    created by @TO decomposeMonomialAlgebra@, @TO decomposeHomogeneousMA@,  @TO monomialAlgebra@.

    The standard option is @TO ZZ@/101.
///


doc ///
  Key
    [decomposeMonomialAlgebra,Verbose]
  Headline
    Option to print intermediate results.
  Description
   Text
    Option to print intermediate results. The standard value is 0 (= do not print).

///


doc ///
  Key
    [decomposeHomogeneousMA,Verbose]
  Headline
    Option to print intermediate results.
  Description
   Text
    Option to print intermediate results. The standard value is 0 (= do not print).

///

doc ///
  Key
    [degreeMA,Verbose]
  Headline
    Option to print intermediate results.
  Description
   Text
    Option to print intermediate results. The standard value is 0 (= do not print).

///


doc ///
  Key
    ReturnMingens
    [decomposeMonomialAlgebra,ReturnMingens]
    [decomposeHomogeneousMA,ReturnMingens]
  Headline
    Option to return the minimal generating set B_A of K[B] as K[A]-module.
  Description
   Text
     Option to return the minimal generating set B_A of K[B] as K[A]-module. Used by @TO isSeminormalMA@ and @TO isNormalMA@.
///


doc ///
  Key
    isCohenMacaulayMA
    (isCohenMacaulayMA,PolynomialRing)
    (isCohenMacaulayMA,List)
    (isCohenMacaulayMA,MonomialAlgebra)
  Headline
    Test whether a simplicial monomial algebra is Cohen-Macaulay.
  Usage
    isCohenMacaulayMA R
    isCohenMacaulayMA B
    isCohenMacaulayMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :Boolean
  Description
   Text
     Test whether the simplicial monomial algebra K[B] is Cohen-Macaulay.

     Note that this condition does not depend on K.

   Example
     a=3
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
     isCohenMacaulayMA R
     decomposeMonomialAlgebra R
   Text

   Example
     a=4
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
     isCohenMacaulayMA R
     decomposeMonomialAlgebra R
   Text

   Example
     a=4
     M=monomialAlgebra {{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     isCohenMacaulayMA M
///


doc ///
  Key
    isGorensteinMA
    (isGorensteinMA,PolynomialRing)
    (isGorensteinMA,List)
    (isGorensteinMA,MonomialAlgebra)
  Headline
    Test whether a simplicial monomial algebra is Gorenstein.
  Usage
    isGorensteinMA R
    isGorensteinMA B
    isGorensteinMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :Boolean
  Description
   Text
     Test whether the simplicial monomial algebra K[B] is Gorenstein.

     Note that this condition does not depend on K.

   Example
     R=QQ[x_0..x_2,Degrees=>{{2, 0}, {0, 2}, {1, 1}}]
     isGorensteinMA R
   Text

     Not Gorenstein:

   Example
     B={{3, 0}, {0, 3}, {1, 2}, {2, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
     isGorensteinMA R
   Text

     Not even Cohen-Macaulay:

   Example
     B={{4, 0}, {0, 4}, {1, 3}, {3, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
     isGorensteinMA R
     isCohenMacaulayMA R
   Text

     Gorenstein:

   Example
     R=QQ[x_0..x_4,Degrees=>{{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}]
     isGorensteinMA R
     decomposeMonomialAlgebra R
   Text

   Example
     R=QQ[x_0..x_4,Degrees=>{{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}]
     M=monomialAlgebra R
     isGorensteinMA M
///

doc ///
  Key
    isBuchsbaumMA
    (isBuchsbaumMA,PolynomialRing)
    (isBuchsbaumMA,List)
    (isBuchsbaumMA,MonomialAlgebra)
  Headline
    Test whether a simplicial monomial algebra is Buchsbaum.
  Usage
    isBuchsbaumMA R
    isBuchsbaumMA B
    isBuchsbaumMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :Boolean
  Description
   Text
     Test whether the simplicial monomial algebra K[B] is Buchsbaum.

     Note that this condition does not depend on K.

     For the definition of Buchsbaum see:

     J. Stueckrad, W. Vogel: Castelnuovo Bounds for Certain Subvarieties in \mathbb{P}^n, Math. Ann. 276 (1987), 341-352.

   Example
     R=QQ[x_0..x_3,Degrees=>{{6,0},{0,6},{4,2},{1,5}}]
     isBuchsbaumMA R
     decomposeMonomialAlgebra R
   Text

   Example
     R=QQ[x_0..x_3,Degrees=>{{4,0},{0,4},{3,1},{1,3}}]
     isBuchsbaumMA R
     decomposeMonomialAlgebra R
   Text

   Example
     R=QQ[x_0..x_3,Degrees=>{{5,0},{0,5},{4,1},{1,4}}]
     isBuchsbaumMA R
     decomposeMonomialAlgebra R
   Text

   Example
     R=QQ[x_0..x_3,Degrees=>{{5,0},{0,5},{4,1},{1,4}}]
     M=monomialAlgebra R
     isBuchsbaumMA M
///


doc ///
  Key
    isSeminormalMA
    (isSeminormalMA,PolynomialRing)
    (isSeminormalMA,List)
    (isSeminormalMA,MonomialAlgebra)
  Headline
    Test whether a simplicial monomial algebra is seminormal.
  Usage
    isSeminormalMA R
    isSeminormalMA B
    isSeminormalMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :Boolean
  Description
   Text
     Test whether the simplicial monomial algebra K[B] is seminormal.

     Note that this condition does not depend on K.

     For the definition of seminormal see:

     Richard G. Swan: On Seminormality, J. Algebra 67, no. 1 (1980), 210-229.

   Example
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     R=QQ[x_0..x_4,Degrees=>B]
     isSeminormalMA R
     isNormalMA R
   Text

   Example
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     M=monomialAlgebra B
     isSeminormalMA M
     isNormalMA M
///


doc ///
  Key
    isNormalMA
    (isNormalMA,PolynomialRing)
    (isNormalMA,List)
    (isNormalMA,MonomialAlgebra)
  Headline
    Test whether a simplicial monomial algebra is normal.
  Usage
    isNormalMA R
    isNormalMA B
    isNormalMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :Boolean
  Description
   Text
     Test whether the simplicial monomial algebra K[B] is normal.

     Note that this condition does not depend on K.

   Example
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     R=QQ[x_0..x_4,Degrees=>B]
     isNormalMA R
     isSeminormalMA R
   Text

   Example
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     M=monomialAlgebra B
     isNormalMA M
     isSeminormalMA M

///



doc ///
  Key
    isSimplicialMA
    (isSimplicialMA,List)
    (isSimplicialMA,PolynomialRing)
    (isSimplicialMA,MonomialAlgebra)
  Headline
    Test whether a monomial algebra is simplicial.
  Usage
    isSimplicialMA R
    isSimplicialMA B
    isSimplicialMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :Boolean
  Description
   Text
     Test whether the monomial algebra K[B] is simplicial, that is, the cone C(B) is spanned by
     linearly independent vectors.

     Note that this condition does not depend on K.

   Example
     B={{1,0,0},{0,2,0},{0,0,2},{1,0,1},{0,1,1}}
     R=QQ[x_0..x_4,Degrees=>B]
     isSimplicialMA R
     isSimplicialMA B
   Text

   Example
     B={{1,0,1},{0,1,1},{1,1,1},{0,0,1}}
     R=QQ[x_0..x_3,Degrees=>B]
     isSimplicialMA R
     isSimplicialMA B
   Text

   Example
     B={{1,0,1},{0,1,1},{1,1,1},{0,0,1}}
     M=monomialAlgebra B
     isSimplicialMA M
///



doc ///
  Key
    findGeneratorsOfSubalgebra
    (findGeneratorsOfSubalgebra,List)
  Headline
    Find submonoid corresponding to the convex hull.
  Usage
    findGeneratorsOfSubalgebra B
  Inputs
    B : List
         with generators of an affine semigroup in \mathbb{N}^d.
  Outputs
    :List
         of elements of B.
  Description
   Text
     Denote by C(B) the cone in \mathbb{R}^d spanned by B. This function computes
     on each ray of C(B) one element of B which has minimal coordinate sum, and
      returns a list of those elements.

   Example
     a=3
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     findGeneratorsOfSubalgebra B
   Text

   Example
     a=4
     B={{a, 0}, {2, a-2}, {1, a-1}, {a-1, 1}}
     findGeneratorsOfSubalgebra B
   Text

   Example
     B={{3, 0}, {2, 0}, {1, 1}, {0, 2}}
     findGeneratorsOfSubalgebra B
///


doc ///
  Key
    findMonomialSubalgebra
    (findMonomialSubalgebra,PolynomialRing)
    (findMonomialSubalgebra,MonomialAlgebra)
  Headline
    Find monomial subalgebra corresponding to the convex hull.
  Usage
    findMonomialSubalgebra M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    M : MonomialAlgebra
  Outputs
    :PolynomialRing
    :MonomialAlgebra
  Description
   Text
     Denote by C(B) the cone in \mathbb{R}^d spanned by B. This function computes
     on each ray of C(B) one element of B which has minimal coordinate sum, and
     returns the multigraded polynomial ring with the corresponding variables.

     If a monomial algebra is specified the function returns a monomial algebra.

   Example
     a=3
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_0..x_3, Degrees=> B]
     findMonomialSubalgebra R
   Text

   Example
     a=3
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     M=monomialAlgebra B
     findMonomialSubalgebra M
///



doc ///
  Key
    Decomposition
    [regularityMA,Decomposition]
  Headline
    Optional argument of regularityMA to specify the decomposition.
  Description
   Text
    Using this argument the decomposition computed by @TO decomposeMonomialAlgebra@ can be specified if known a priori.

///


doc ///
  Key
    regularityMA
    (regularityMA,PolynomialRing)
    (regularityMA,List)
    (regularityMA,MonomialAlgebra)
  Headline
    Compute regularity from decomposition
  Usage
    regularityMA R
    regularityMA B
    regularityMA M
  Inputs
    R  : PolynomialRing
           with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B  : List
           with the generators of an affine semigroup in \mathbb{N}^d.
           In the case B is specified, K is set via the @TO Option@ @TO CoefficientField@.
           If a list of positive integers is given, the function uses @TO adjoinPurePowers@ and @TO homogenizeSemigroup@
           to convert it into a list of elements of \mathbb{N}^2.
    M : MonomialAlgebra
  Outputs
    :ZZ
       list of the regularity and list of the summands achieving the maximum
  Description
   Text

     Compute the regularity of K[B] from the decomposition of the homogeneous monomial algebra K[B].

     We assume that B=<b_{1},...,b_{r}> is homogeneous and minimally generated by b_{1},...,b_{r}, that is, there is a group homomorphism \phi : G(B) \to \mathbb{Z} such that \phi(b_{i}) = 1 for all i.

     In the case of a monomial curve an ad hoc formula for the regularity of the components is used (if R or B is given).

     Specifying R:

   Example
     a=5
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
     regularityMA R
   Text

     Specifying a monomial algebra:

   Example
     a=5
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     M=monomialAlgebra B
     regularityMA M
   Text

     Specifying the decomposition dc:

   Example
     a=5
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     R=QQ[x_0..x_3,Degrees=>B]
     dc=decomposeMonomialAlgebra R
     regularityMA(B,Decomposition=>dc)
   Text

     Specifying B:

   Example
     a=5
     B={{a, 0}, {0, a}, {1, a-1}, {a-1, 1}}
     regularityMA B
   Text

     Compare to

   Example
     I=ker map(QQ[s,t],QQ[x_0..x_3],matrix {{s^a,t^a,s*t^(a-1),s^(a-1)*t}})
     -1+regularity I
///


doc ///
  Key
    degreeMA
    (degreeMA,PolynomialRing)
    (degreeMA,List)
    (degreeMA,MonomialAlgebra)
  Headline
    Degree of a monomial algebra.
  Usage
    degreeMA R
    degreeMA B
    degreeMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    B : MonomialAlgebra
  Outputs
    :ZZ
  Description
   Text
     Compute the degree of the homogeneous monomial algebra K[B].

     As the result is independent of K it is possible to specify just B.

   Example
     B={{2, 2, 1}, {1, 1, 3}, {1, 2, 2}, {2, 0, 3}, {1, 4, 0}, {2, 3, 0}, {1, 3, 1}}
     R=QQ[x_1..x_(#B),Degrees=>B]
     degreeMA R
   Text

   Example
     B={{2, 2, 1}, {1, 1, 3}, {1, 2, 2}, {2, 0, 3}, {1, 4, 0}, {2, 3, 0}, {1, 3, 1}}
     M=monomialAlgebra B
     degreeMA M
///

doc ///
  Key
    codimMA
    (codimMA,List)
    (codimMA,PolynomialRing)
    (codimMA,MonomialAlgebra)
  Headline
    Codimension of a monomial algebra.
  Usage
    codimMA R
    codimMA B
    codimMA M
  Inputs
    R : PolynomialRing
          with B = @TO degrees@ R and K = @TO coefficientRing@ R, or
    B : List
          with the generators of an affine semigroup in \mathbb{N}^d.
    M : MonomialAlgebra
  Outputs
    :ZZ
  Description
   Text
     Compute the codimension of the homogeneous monomial algebra K[B].

     As the result is independent of K it is possible to specify just B.

   Example
     B={{2, 2, 1}, {1, 1, 3}, {1, 2, 2}, {2, 0, 3}, {1, 4, 0}, {2, 3, 0}, {1, 3, 1}}
     codimMA B
   Text

   Example
     B={{2, 2, 1}, {1, 1, 3}, {1, 2, 2}, {2, 0, 3}, {1, 4, 0}, {2, 3, 0}, {1, 3, 1}}
     M=monomialAlgebra B
     codimMA M
///





doc ///
  Key
    randomSemigroup
    (randomSemigroup,ZZ,ZZ,ZZ)
  Headline
    Generate random semigroups.
  Usage
    randomSemigroup(a,d,c)
  Inputs
    a:ZZ
       positive
    d:ZZ
       positive
    c:ZZ
       positive
  Outputs
    L:List
  Description
   Text
     Generate a random generating set of a semigroups B in \mathbb{N}^d of full
     dimension with coordinate sum a and codimension c.

     Note that the random number generator can be controlled by the command @TO setRandomSeed@.
     Alternatively you can also use the option @TO SetSeed@.

     The option @TO Num@ can be used to return a list of semigroups.

     The option @TO Simplicial@ can be used to return a simplicial semigroup
     such that the standard vectors a*e_i are among the Hilbert basis.

   Example
     randomSemigroup(5,3,7)
     setRandomSeed()
     randomSemigroup(5,3,7)
     setRandomSeed()
     randomSemigroup(5,3,7)
     setRandomSeed()
     randomSemigroup(5,3,7,Num=>2)
     setRandomSeed()
     randomSemigroup(5,3,7,Simplicial=>true)
///

doc ///
  Key
    randomMonomialAlgebra
    (randomMonomialAlgebra,ZZ,ZZ,ZZ)
  Headline
    Generate random monomial algebra.
  Usage
    randomMonomialAlgebra(a,d,c)
  Inputs
    a:ZZ
       positive
    d:ZZ
       positive
    c:ZZ
       positive
  Outputs
     :MonomialAlgebra
           or a list of those if the option @TO Num@ is bigger or equal to 2.
  Description
   Text
     Generate a random monomial algebra such that the semigroup generated by the degrees
     is in \mathbb{N}^d of full
     dimension with coordinate sum a and codimension c.

     Note that the random number generator can be controlled by the command @TO setRandomSeed@.
     Alternatively you can also use the option @TO SetSeed@.

     The option @TO Num@ can be used to return a list of semigroups.

     The option @TO Simplicial@ can be used to return a simplicial semigroup
     such that the standard vectors a*e_i are among the Hilbert basis.

   Example
     randomMonomialAlgebra(5,3,7)
     setRandomSeed()
     randomMonomialAlgebra(5,3,7)
     setRandomSeed()
     randomMonomialAlgebra(5,3,7)
     setRandomSeed()
     randomMonomialAlgebra(5,3,7,Num=>2)
     setRandomSeed()
     randomMonomialAlgebra(5,3,7,Simplicial=>true)
///


doc ///
  Key
    Simplicial
    [randomSemigroup,Simplicial]
    [randomMonomialAlgebra,Simplicial]
  Headline
    Option of randomSemigroup and randomMonomialAlgebra to return a simplicial semigroup.
  Description
   Text
    Option of @TO randomSemigroup@ and @TO randomMonomialAlgebra@ to return a set of generators of a simplicial semigroup
    (with coordinate sum a) such that the standard vectors a*e_i are among the Hilbert basis.

    The default value is false.
///



doc ///
  Key
    Num
    [randomSemigroup,Num]
    [randomMonomialAlgebra,Num]
  Headline
    Option of randomSemigroup and randomMonomialAlgebra to return a list of several semigroups.
  Description
   Text
    Option of @TO randomSemigroup@ and @TO randomMonomialAlgebra@ to return a list of several semigroups.

    The default value is 1.
///

doc ///
  Key
    SetSeed
    [randomSemigroup,SetSeed]
    [randomMonomialAlgebra,SetSeed]
  Headline
    Option to set the random seed for randomSemigroup and randomMonomialAlgebra.
  Description
   Text
    Option to set the random seed for @TO randomSemigroup@ and @TO randomMonomialAlgebra@.

    For the standard option false Macaulay2 automatically produces a random seed from various system parameters.

    If the option is true, then the command @TO setRandomSeed@() is applied upon initialization of the function to use always the standard Macaulay2 random seed.

    If the option is set to an integer r then @TO setRandomSeed@(r) is applied.
///




-*
restart
uninstallPackage("MonomialAlgebras")
installPackage("MonomialAlgebras",RerunExamples=>true);
installPackage("MonomialAlgebras");
check MonomialAlgebras
viewHelp MonomialAlgebras
*-

end
restart
installPackage "MonomialAlgebras"
check "MonomialAlgebras"

restart
needsPackage "MonomialAlgebras";
B = {{4,0,0},{2,2,0},{2,0,2},{0,2,2},{0,3,1},{3,1,0},{1,1,2}};
K = ZZ/101;
S = K[x_1..x_7, Degrees=>B];
IB = binomialIdeal S;
R = newRing(ring IB, Degrees => {7:1});
betti res sub(IB,R)
dc = decomposeMonomialAlgebra S

KA = ring first first values dc;
T = newRing(ring ideal KA, Degrees => {5:1});
J = sub(ideal KA,T);
betti res J

I1 = first (values dc)#0
g = matrix entries sub(gens I1, T);
betti res image map(coker gens J, source g, g)

regularityMA S

degree J

B = {{4,0,0},{0,4,0},{0,0,4},{1,0,3},{0,2,2},{3,0,1},{1,2,1}};
S = K[x_1..x_7, Degrees => B];
decomposeMonomialAlgebra S

isSeminormalMA B

isBuchsbaumMA B
