\documentclass{article}
\usepackage{axiom}
\begin{document}
\title{\$SPAD/src/input hilbert.as}
\author{The Axiom Team}
\maketitle
\begin{abstract}
\end{abstract}
\eject
\tableofcontents
\eject
\section{Hilbert input tests}
<>=
)compile hilbert.as
mon1 := monom(4,0,0,0)
mon2:= monom(3,3,0,0)
mon3 := monom(3,2,1,0)
mon4 := monom(3,1,2,0)
mon5 := monom(0,2,0,1)
mon6 := monom(0,1,0,5)
l := [mon1, mon2, mon3, mon4, mon5, mon6]
Hilbert l
idA := varMonomsPower(6,5);
#idA
Hilbert idA
idB := varMonomsPower(6,6);
#idB
Hilbert idB
idC := varMonomsPower(12,3);
#idC
Hilbert idC
idD:=[monom(2,0,0,0),monom(1,1,0,0),monom(1,0,1,0),monom(1,0,0,1),_
monom(0,3,0,0),monom(0,2,1,0)]^4;
#idD
Hilbert idD
@
\section{License}
<>=
-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are
-- met:
--
-- - Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
--
-- - Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in
-- the documentation and/or other materials provided with the
-- distribution.
--
-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
-- names of its contributors may be used to endorse or promote products
-- derived from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@
<<*>>=
<>
<>
#include "axiom.as"
#pile
-- This file computes hilbert functions for monomial ideals
-- ref: "On the Computation of Hilbert-Poincare Series",
-- Bigatti, Caboara, Robbiano,
-- AAECC vol 2 #1 (1991) pp 21-33
macro
Monom == Monomial
L == List
SI == SingleInteger
B == Boolean
POLY == SparseUnivariatePolynomial Integer
Array == Vector
import from NonNegativeInteger
import from SingleInteger
import from Segment SI
import from Integer
Monomial : OrderedSet with
totalDegree: % -> SI
divides?: (%, %) -> B
homogLess: (%, %) -> B
quo: (%, %) -> %
quo: (%, SI) -> %
*: (%, %) -> %
varMonom: (i:SI,n:SI, deg:SI) -> %
variables: L % -> L SI
apply: (%, SI) -> SI
#: % -> SI
monom: Tuple SI -> %
== Array(SingleInteger) add
Rep ==> Array(SingleInteger)
import from Rep
monom(t:Tuple SI):% == per [ t ]
totalDegree(m:%):SI ==
sum:SI := 0
for e in rep m repeat sum := sum + e
sum
divides?(m1:%, m2:%):B ==
for e1 in rep m1 for e2 in rep m2 repeat
if e1 > e2 then return false
true
(m1:%) < (m2:%):B ==
for e1 in rep m1 for e2 in rep m2 repeat
if e1 < e2 then return true
if e1 > e2 then return false
false
-- (m1:%) > (m2:%):B == m2 < m1
homogLess(m1:%, m2:%):B ==
(d1:=totalDegree(m1)) < (d2:=totalDegree(m2)) => true
d1 > d2 => false
( m1 < m2)
(m:%) quo (v:SI):% == --remove vth variable
-- per [((if i=v then 0 else (rep m).i) for i in 1..#rep m)]
m2:= copy rep m
m2.v := 0
per m2
(m1:%) quo (m2:%):% ==
per [(max(a1-a2,0) for a1 in rep m1 for a2 in rep m2)]
(m1:%) * (m2:%):% == per [(a1+a2 for a1 in rep m1 for a2 in rep m2)]
varMonom(i:SI,n:SI, deg:SI):% ==
-- per [((if j=i then deg else 0$SI) for j in 1..n)]
m:Rep := new(n, 0)
m.i := deg
per m
variables(I:L %) :L SI ==
empty? I => nil
n:SI:=# rep first I
ans : L SI := nil
v:SI:=0
while (v:=v+1)<=n repeat
-- for v in 1..n repeat
for m in I repeat
(rep m).v ~= 0 =>
ans := cons(v, ans)
break
ans
HilbertFunctionPackage: with
Hilbert: L Monom -> POLY
adjoin: (Monom, L Monom) -> L Monom
== add
adjoin(m:Monom, lm:L Monom):L Monom ==
empty?(lm) => cons(m, nil)
ris1:L Monom:= empty()
ris2:L Monom:= empty()
while not empty? lm repeat
m1:Monom := first lm
lm := rest lm
if m <= m1 then
if not divides?(m,m1) then (ris1 := cons(m1, ris1))
iterate
ris2 := cons(m1, ris2)
if divides?(m1, m) then
return concat!(reverse!(ris1), concat!(reverse! ris2, lm))
concat!(reverse!(ris1), cons(m, reverse! ris2))
reduce(lm:L Monom):L Monom ==
lm := sortHomogRemDup(lm)
empty? lm => lm
ris :L Monom := nil
risd:L Monom := list first lm
d := totalDegree first lm
for m in rest lm repeat
if totalDegree(m)=d then risd := cons(m, risd)
else
ris := mergeDiv(ris, risd)
d := totalDegree m
risd := [m]
mergeDiv(ris, risd)
mergeDiv( small:L Monom, big:L Monom): L Monom ==
ans : L Monom := small
for m in big repeat
if not contained?(m,small) then ans := cons(m, ans)
ans
contained?(m:Monom, id: L Monom) : B ==
for mm in id repeat
divides?(mm, m) => return true
false
(I:L Monom) quo (m:Monom):L Monom ==
reduce [mm quo m for mm in I]
sort(I:L Monom, v:SI):L Monom ==
sort((a:Monom,b:Monom):B+->(a.v < b.v), I)
sortHomogRemDup(l:L Monom):L Monom ==
l:=sort(homogLess, l)
empty? l => l
ans:L Monom := list first l
for m in rest l repeat
if m ~= first(ans) then ans:=cons(m, ans)
reverse! ans
decompose(I:L Monom, v:SI):Record(size:SI, ideals:L L Monom, degs:L SI) ==
I := sort(I, v)
idlist: L L Monom := nil
deglist : L SI := nil
size : SI := 0
J: L Monom := nil
while not empty? I repeat
d := first(I).v
tj : L Monom := nil
local m:Monom
while not empty? I and d=(m:=first I).v repeat
tj := cons(m quo v, tj)
I := rest I
J := mergeDiv(tj, J)
idlist := cons(J, idlist)
deglist := cons(d, deglist)
size := size + ((#J)::Integer::SI)
[size, idlist, deglist]
var(n:SI) : SparseUnivariatePolynomial Integer ==
monomial(1$Integer, n::Integer::NonNegativeInteger)
Hilbert(I:L Monom):POLY ==
empty? I => 1 -- no non-zero generators = 0 ideal
empty? rest I => var(0) - var(totalDegree first I)
lvar :L SI := variables I
import from Record(size:SI, ideals:L L Monom, degs:L SI)
Jbest := decompose(I, first lvar)
for v in rest lvar while (#I)::Integer::SI < Jbest.size repeat
JJ := decompose(I, v)
JJ.size < Jbest.size => Jbest := JJ
import from L L Monom
import from L SI
Jold:List Monom := first(Jbest.ideals)
dold:SI := first(Jbest.degs)
f:SparseUnivariatePolynomial Integer:=var(dold)*Hilbert(Jold)
for J:List Monom in rest Jbest.ideals for d:SI in rest Jbest.degs repeat
f := f + (var(d) - var(dold)) * Hilbert(J)
dold := d
var(0) - var(dold) + f
MonomialIdealPackage: with
varMonomsPower: (SI, SI) -> L Monom
*: (L Monom, L Monom) -> L Monom
^: (L Monom, SI) -> L Monom
== add
varMonoms(n:SI):L Monom ==
-- [varMonom(i,n,1) for i in 1..n]
i:SI:=0
[varMonom(i,n,1) while {free i; (i:=i+1)<=n}]
varMonomsPower(n:SI, deg:SI):L Monom ==
n = 1 => [ monom(deg)]
ans : L Monom := nil
-- for j in 0..deg repeat
j:SI:=-1
while (j:=j+1)<=deg repeat
ans := concat(varMonomMult(j,varMonomsPower(n-1,deg-j)), ans)
ans
varMonomMult(i:SI, mlist : L Monom) : L Monom ==
[varMonomMult(i, m) for m in mlist]
varMonomMult(i:SI, m:Monom) : Monom ==
nm:Array SI := new(#m + 1, i)
-- for k in 1..#m repeat nm.k :=m.k
k:SI:=0
while (k:=k+1)<=#m repeat nm.k :=m.k
nm pretend Monom
(i1:L Monom) * (i2:L Monom):L Monom ==
import from HilbertFunctionPackage
ans : L Monom := nil
for m1 in i1 repeat for m2 in i2 repeat
ans := adjoin(m1*m2, ans)
ans
(i:L Monom) ^ (n:SI) : L Monom ==
n = 1 => i
odd? n => i * (i*i)^shift(n, -1)
(i*i)^shift(n,-1)
@
\eject
\begin{thebibliography}{99}
\bibitem{1} nothing
\end{thebibliography}
\end{document}