aboutsummaryrefslogtreecommitdiff
path: root/src/booklets/Sorting.booklet
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2007-12-27 18:19:40 +0000
committerdos-reis <gdr@axiomatics.org>2007-12-27 18:19:40 +0000
commit3e444950379ac4536b158da4c0469914ac5548e5 (patch)
tree33cdcd551e5d7a45ebaaa1b31027d0d7eb2d9736 /src/booklets/Sorting.booklet
parent7c4231fc804407ed504ecb79fb2a381d251aab74 (diff)
downloadopen-axiom-3e444950379ac4536b158da4c0469914ac5548e5.tar.gz
Remove booklets directory
Diffstat (limited to 'src/booklets/Sorting.booklet')
-rwxr-xr-xsrc/booklets/Sorting.booklet2731
1 files changed, 0 insertions, 2731 deletions
diff --git a/src/booklets/Sorting.booklet b/src/booklets/Sorting.booklet
deleted file mode 100755
index 2f43240f..00000000
--- a/src/booklets/Sorting.booklet
+++ /dev/null
@@ -1,2731 +0,0 @@
-\documentclass{article}
-\usepackage{/home/axiomgnu/new/mnt/linux/bin/tex/noweb}
-\begin{document}
-\title{Sorting Facilities}
-\author{Timothy Daly}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-This is a survey of the explicitly mentioned sorting algorithms
-in the Axiom algebra code. Note that there are cases of "embedded"
-sorts as in the {\bf chainSubResultants} method from the
-{\bf PseudoRemainderSequence \cite{1}} domain. There are also
-implicit sorts as items are added to lists individually in sorted
-order.
-\subsection{aggcat.spad}
-\subsubsection{FiniteLinearAggregate}
-++ A finite linear aggregate is a linear aggregate of finite length.
-++ The finite property of the aggregate adds several exports to the
-++ list of exports from {\bf LinearAggregate} such as
-++ {\bf reverse}, {\bf sort}, and so on.
-<<FiniteLinearAggregate>>=
-FiniteLinearAggregate(S:Type): Category == LinearAggregate S with
- finiteAggregate
- sort: ((S,S)->B,%) -> %
- ++ sort(p,a) returns a copy of {\bf a} sorted
- ++ using total ordering predicate p.
- if S has OrderedSet then
- OrderedSet
- sort: % -> %
- ++ sort(u) returns an u with elements in ascending order.
- ++ Note: {\bf sort(u) = sort(<=,u)}.
- if % has shallowlyMutable then
- sort_!: ((S,S)->B,%) -> %
- ++ sort!(p,u) returns u with its elements ordered by p.
- if S has OrderedSet then sort_!: % -> %
- ++ sort!(u) returns u with its elements in ascending order.
- add
- if S has OrderedSet then
- sort l == sort(_<$S, l)
-
- if % has shallowlyMutable then
- sort(f, l) == sort_!(f, copy l)
- if S has OrderedSet then
- sort_! l == sort_!(_<$S, l)
-
-@
-\subsubsection{OneDimensionalArrayAggregate}
-One-dimensional-array aggregates serves as models for one-dimensional arrays.
-Categorically, these aggregates are finite linear aggregates
-with the {\bf shallowlyMutable} property, that is, any component of
-the array may be changed without affecting the
-identity of the overall array.
-Array data structures are typically represented by a fixed area in storage and
-therefore cannot efficiently grow or shrink on demand as can list structures
-(see however {\bf FlexibleArray} for a data structure which
-is a cross between a list and an array).
-Iteration over, and access to, elements of arrays is extremely fast
-(and often can be optimized to open-code).
-Insertion and deletion however is generally slow since an entirely new
-data structure must be created for the result.
-
-<<OneDimensionalArrayAggregate>>=
-OneDimensionalArrayAggregate(S:Type): Category ==
- FiniteLinearAggregate S with shallowlyMutable
- add
- sort_!(f, a) == quickSort(f, a)$FiniteLinearAggregateSort(S, %)
-
-@
-\subsubsection{ListAggregate}
-A list aggregate is a model for a linked list data structure.
-A linked list is a versatile
-data structure. Insertion and deletion are efficient and
-searching is a linear operation.
-
-{\bf ListAggregate} uses the operation {\bf split\_!} which is inherited from
-{\bf StreamAggregate} which inherites it from it's implementing Domain
-{\bf UnaryRecursiveAggregate}.
-A unary-recursive aggregate is a one where nodes may have either
-0 or 1 children.
-This aggregate models, though not precisely, a linked
-list possibly with a single cycle.
-A node with one children models a non-empty list, with the
-{\bf value} of the list designating the head, or {\bf first}, of the
-list, and the child designating the tail, or {\bf rest}, of the list.
-A node with no child then designates the empty list.
-Since these aggregates are recursive aggregates, they may be cyclic.
-
-There we see the definition of {\bf split\_!} as:
-
-<<UnaryRecursiveAggregate>>=
-UnaryRecursiveAggregate(S:Type): Category == RecursiveAggregate S with
- rest: % -> %
- ++ rest(u) returns an aggregate consisting of all but the first
- ++ element of u
- ++ (equivalently, the next node of u).
- rest: (%,N) -> %
- ++ rest(u,n) returns the \axiom{n}th (n >= 0) node of u.
- ++ Note: \axiom{rest(u,0) = u}.
- if % has shallowlyMutable then
- split_!: (%,I) -> %
- ++ split!(u,n) splits u into two aggregates: \axiom{v = rest(u,n)}
- ++ and \axiom{w = first(u,n)}, returning \axiom{v}.
- ++ Note: afterwards \axiom{rest(u,n)} returns \axiom{empty()}.
- add
- rest(x, n) ==
- for i in 1..n repeat
- empty? x => error "Index out of range"
- x := rest x
- x
-
- if S has SetCategory then
- split_!(p, n) ==
- n < 1 => error "index out of range"
- p := rest(p, (n - 1)::N)
- q := rest p
- setrest_!(p, empty())
- q
-
-
-@
-<<ListAggregate>>=
-ListAggregate(S:Type): Category == Join(StreamAggregate S,
- FiniteLinearAggregate S, ExtensibleLinearAggregate S) with
- add
- mergeSort: ((S, S) -> B, %, I) -> %
- mergeSort(f, p, n) ==
- if n = 2 and f(first rest p, first p) then p := reverse_! p
- n < 3 => p
- l := (n quo 2)::N
- q := split_!(p, l)
- p := mergeSort(f, p, l)
- q := mergeSort(f, q, n - l)
- merge_!(f, p, q)
-
- reverse_! x ==
- empty? x => x
- empty?(y := rest x) => x
- setrest_!(x, empty())
- while not empty? y repeat
- z := rest y
- setrest_!(y, x)
- x := y
- y := z
- x
-
- merge_!(f, p, q) ==
- empty? p => q
- empty? q => p
- eq?(p, q) => error "cannot merge a list into itself"
- if f(first p, first q)
- then (r := t := p; p := rest p)
- else (r := t := q; q := rest q)
- while not empty? p and not empty? q repeat
- if f(first p, first q)
- then (setrest_!(t, p); t := p; p := rest p)
- else (setrest_!(t, q); t := q; q := rest q)
- setrest_!(t, if empty? p then q else p)
- r
-
- sort_!(f, l) == mergeSort(f, l, #l)
-
- list x == concat(x, empty())
- reduce(f, x) ==
- empty? x => error "reducing over an empty list needs the 3 argument form"
- reduce(f, rest x, first x)
- merge(f, p, q) == merge_!(f, copy p, copy q)
-
- select_!(f, x) ==
- while not empty? x and not f first x repeat x := rest x
- empty? x => x
- y := x
- z := rest y
- while not empty? z repeat
- if f first z then (y := z; z := rest z)
- else (z := rest z; setrest_!(y, z))
- x
-
- insert_!(s:S, x:%, i:I) ==
- i < (m := minIndex x) => error "index out of range"
- i = m => concat(s, x)
- y := rest(x, (i - 1 - m)::N)
- z := rest y
- setrest_!(y, concat(s, z))
- x
-
- insert_!(w:%, x:%, i:I) ==
- i < (m := minIndex x) => error "index out of range"
- i = m => concat_!(w, x)
- y := rest(x, (i - 1 - m)::N)
- z := rest y
- setrest_!(y, w)
- concat_!(y, z)
- x
-
- remove_!(f:S -> B, x:%) ==
- while not empty? x and f first x repeat x := rest x
- empty? x => x
- p := x
- q := rest x
- while not empty? q repeat
- if f first q then q := setrest_!(p, rest q)
- else (p := q; q := rest q)
- x
-
- delete_!(x:%, i:I) ==
- i < (m := minIndex x) => error "index out of range"
- i = m => rest x
- y := rest(x, (i - 1 - m)::N)
- setrest_!(y, rest(y, 2))
- x
-
- delete_!(x:%, i:U) ==
- (l := lo i) < (m := minIndex x) => error "index out of range"
- h := if hasHi i then hi i else maxIndex x
- h < l => x
- l = m => rest(x, (h + 1 - m)::N)
- t := rest(x, (l - 1 - m)::N)
- setrest_!(t, rest(t, (h - l + 2)::N))
- x
-
- find(f, x) ==
- while not empty? x and not f first x repeat x := rest x
- empty? x => "failed"
- first x
-
- position(f:S -> B, x:%) ==
- for k in minIndex(x).. while not empty? x and not f first x repeat
- x := rest x
- empty? x => minIndex(x) - 1
- k
-
- sorted?(f, l) ==
- empty? l => true
- p := rest l
- while not empty? p repeat
- not f(first l, first p) => return false
- p := rest(l := p)
- true
-
- reduce(f, x, i) ==
- r := i
- while not empty? x repeat (r := f(r, first x); x := rest x)
- r
-
- if S has SetCategory then
- reduce(f, x, i,a) ==
- r := i
- while not empty? x and r ^= a repeat
- r := f(r, first x)
- x := rest x
- r
-
- new(n, s) ==
- l := empty()
- for k in 1..n repeat l := concat(s, l)
- l
-
- map(f, x, y) ==
- z := empty()
- while not empty? x and not empty? y repeat
- z := concat(f(first x, first y), z)
- x := rest x
- y := rest y
- reverse_! z
-
- copy x ==
- y := empty()
- for k in 0.. while not empty? x repeat
- k = cycleMax and cyclic? x => error "cyclic list"
- y := concat(first x, y)
- x := rest x
- reverse_! y
-
- copyInto_!(y, x, s) ==
- s < (m := minIndex y) => error "index out of range"
- z := rest(y, (s - m)::N)
- while not empty? z and not empty? x repeat
- setfirst_!(z, first x)
- x := rest x
- z := rest z
- y
-
- if S has SetCategory then
- position(w, x, s) ==
- s < (m := minIndex x) => error "index out of range"
- x := rest(x, (s - m)::N)
- for k in s.. while not empty? x and w ^= first x repeat
- x := rest x
- empty? x => minIndex x - 1
- k
-
- removeDuplicates_! l ==
- p := l
- while not empty? p repeat
- p := setrest_!(p, remove_!(#1 = first p, rest p))
- l
-
- if S has OrderedSet then
- x < y ==
- while not empty? x and not empty? y repeat
- first x ^= first y => return(first x < first y)
- x := rest x
- y := rest y
- empty? x => not empty? y
- false
-
-
-@
-\subsection{alql.spad}
-\subsubsection{DataList}
-This domain provides some nice functions on lists
-<<DataList>>=
-DataList(S:OrderedSet) : Exports == Implementation where
- Exports == ListAggregate(S) with
- elt: (%,"sort") -> %
- ++ {\bf l.sort} returns {\bf l} with elements sorted.
- ++ Note: {\bf l.sort = sort(l)}
- Implementation == List(S) add
- elt(x,"sort") == sort(x)
-
-@
-\subsection{carten.spad}
-\subsubsection{CartesianTensor}
-This is an instance of an "embedded sort" that should probably
-call one of the general purpose sort routines.
-
-{\bf CartesianTensor(minix,dim,R)} provides Cartesian tensors with
-components belonging to a commutative ring R. These tensors
-can have any number of indices. Each index takes values from
-{\bf minix} to {\bf minix + dim - 1}.
-<<CartesianTensor>>=
-CartesianTensor(minix, dim, R): Exports == Implementation where
- Exports ==> Join(GradedAlgebra(R, NNI), GradedModule(I, NNI)) with
- Implementation ==> add
- INDEX ==> Vector Integer -- 1-based entries from minix..minix+dim-1
-
- -- permsign!(v) = 1, 0, or -1 according as
- -- v is an even, is not, or is an odd permutation of minix..minix+#v-1.
- permsign_!(v: INDEX): Integer ==
- -- sum minix..minix+#v-1.
- maxix := minix+#v-1
- psum := (((maxix+1)*maxix - minix*(minix-1)) exquo 2)::Integer
- -- +/v ^= psum => 0
- n := 0
- for i in 1..#v repeat n := n + v.i
- n ^= psum => 0
- -- Bubble sort! This is pretty grotesque.
- totTrans: Integer := 0
- nTrans: Integer := 1
- while nTrans ^= 0 repeat
- nTrans := 0
- for i in 1..#v-1 for j in 2..#v repeat
- if v.i > v.j then
- nTrans := nTrans + 1
- e := v.i; v.i := v.j; v.j := e
- totTrans := totTrans + nTrans
- for i in 1..dim repeat
- if v.i ^= minix+i-1 then return 0
- odd? totTrans => -1
- 1
-
-@
-\subsection{clifford.spad}
-\subsubsection{CliffordAlgebra}
-Examples of {\bf Clifford Algebras} are: gaussians, quaternions, exterior
-algebras and spin algebras.
-<<CliffordAlgebra>>=
-CliffordAlgebra(n, K, Q): T == Impl where
- n: PositiveInteger
- K: Field
- Q: QuadraticForm(n, K)
-
- PI ==> PositiveInteger
- NNI==> NonNegativeInteger
-
- T ==> Join(Ring, Algebra(K), VectorSpace(K)) with
- e: PI -> %
- ++ e(n) produces the appropriate unit element.
- monomial: (K, List PI) -> %
- ++ monomial(c,[i1,i2,...,iN]) produces the value given by
- ++ \spad{c*e(i1)*e(i2)*...*e(iN)}.
- coefficient: (%, List PI) -> K
- ++ coefficient(x,[i1,i2,...,iN]) extracts the coefficient of
- ++ \spad{e(i1)*e(i2)*...*e(iN)} in x.
- recip: % -> Union(%, "failed")
- ++ recip(x) computes the multiplicative inverse of x or "failed"
- ++ if x is not invertible.
-
- Impl ==> add
- Qeelist := [Q unitVector(i::PositiveInteger) for i in 1..n]
- dim := 2**n
-
- Rep := PrimitiveArray K
-
- New ==> new(dim, 0$K)$Rep
-
- x, y, z: %
- c: K
- m: Integer
-
- characteristic() == characteristic()$K
- dimension() == dim::CardinalNumber
-
- x = y ==
- for i in 0..dim-1 repeat
- if x.i ^= y.i then return false
- true
-
- x + y == (z := New; for i in 0..dim-1 repeat z.i := x.i + y.i; z)
- x - y == (z := New; for i in 0..dim-1 repeat z.i := x.i - y.i; z)
- - x == (z := New; for i in 0..dim-1 repeat z.i := - x.i; z)
- m * x == (z := New; for i in 0..dim-1 repeat z.i := m*x.i; z)
- c * x == (z := New; for i in 0..dim-1 repeat z.i := c*x.i; z)
-
- 0 == New
- 1 == (z := New; z.0 := 1; z)
- coerce(m): % == (z := New; z.0 := m::K; z)
- coerce(c): % == (z := New; z.0 := c; z)
-
- e b ==
- b::NNI > n => error "No such basis element"
- iz := 2**((b-1)::NNI)
- z := New; z.iz := 1; z
-
- -- The ei*ej products could instead be precomputed in
- -- a (2**n)**2 multiplication table.
- addMonomProd(c1: K, b1: NNI, c2: K, b2: NNI, z: %): % ==
- c := c1 * c2
- bz := b2
- for i in 0..n-1 | bit?(b1,i) repeat
- -- Apply rule ei*ej = -ej*ei for i^=j
- k := 0
- for j in i+1..n-1 | bit?(b1, j) repeat k := k+1
- for j in 0..i-1 | bit?(bz, j) repeat k := k+1
- if odd? k then c := -c
- -- Apply rule ei**2 = Q(ei)
- if bit?(bz,i) then
- c := c * Qeelist.(i+1)
- bz:= (bz - 2**i)::NNI
- else
- bz:= bz + 2**i
- z.bz := z.bz + c
- z
-
- x * y ==
- z := New
- for ix in 0..dim-1 repeat
- if x.ix ^= 0 then for iy in 0..dim-1 repeat
- if y.iy ^= 0 then addMonomProd(x.ix,ix,y.iy,iy,z)
- z
-
- canonMonom(c: K, lb: List PI): Record(coef: K, basel: NNI) ==
- -- 0. Check input
- for b in lb repeat b > n => error "No such basis element"
-
- -- 1. Apply identity ei*ej = -ej*ei, i^=j.
- -- The Rep assumes n is small so bubble sort is ok.
- -- Using bubble sort keeps the exchange info obvious.
- wasordered := false
- exchanges := 0
- while not wasordered repeat
- wasordered := true
- for i in 1..#lb-1 repeat
- if lb.i > lb.(i+1) then
- t := lb.i; lb.i := lb.(i+1); lb.(i+1) := t
- exchanges := exchanges + 1
- wasordered := false
- if odd? exchanges then c := -c
-
- -- 2. Prepare the basis element
- -- Apply identity ei*ei = Q(ei).
- bz := 0
- for b in lb repeat
- bn := (b-1)::NNI
- if bit?(bz, bn) then
- c := c * Qeelist bn
- bz:= ( bz - 2**bn )::NNI
- else
- bz:= bz + 2**bn
- [c, bz::NNI]
-
- monomial(c, lb) ==
- r := canonMonom(c, lb)
- z := New
- z r.basel := r.coef
- z
- coefficient(z, lb) ==
- r := canonMonom(1, lb)
- r.coef = 0 => error "Cannot take coef of 0"
- z r.basel/r.coef
-
- Ex ==> OutputForm
-
- coerceMonom(c: K, b: NNI): Ex ==
- b = 0 => c::Ex
- ml := [sub("e"::Ex, i::Ex) for i in 1..n | bit?(b,i-1)]
- be := reduce("*", ml)
- c = 1 => be
- c::Ex * be
- coerce(x): Ex ==
- tl := [coerceMonom(x.i,i) for i in 0..dim-1 | x.i^=0]
- null tl => "0"::Ex
- reduce("+", tl)
-
-
- localPowerSets(j:NNI): List(List(PI)) ==
- l: List List PI := list []
- j = 0 => l
- Sm := localPowerSets((j-1)::NNI)
- Sn: List List PI := []
- for x in Sm repeat Sn := cons(cons(j pretend PI, x),Sn)
- append(Sn, Sm)
-
- powerSets(j:NNI):List List PI == map(reverse, localPowerSets j)
-
- Pn:List List PI := powerSets(n)
-
- recip(x: %): Union(%, "failed") ==
- one:% := 1
- -- tmp:c := x*yC - 1$C
- rhsEqs : List K := []
- lhsEqs: List List K := []
- lhsEqi: List K
- for pi in Pn repeat
- rhsEqs := cons(coefficient(one, pi), rhsEqs)
-
- lhsEqi := []
- for pj in Pn repeat
- lhsEqi := cons(coefficient(x*monomial(1,pj),pi),lhsEqi)
- lhsEqs := cons(reverse(lhsEqi),lhsEqs)
- ans := particularSolution(matrix(lhsEqs),
- vector(rhsEqs))$LinearSystemMatrixPackage(K, Vector K, Vector K, Matrix K)
- ans case "failed" => "failed"
- ansP := parts(ans)
- ansC:% := 0
- for pj in Pn repeat
- cj:= first ansP
- ansP := rest ansP
- ansC := ansC + cj*monomial(1,pj)
- ansC
-
-@
-\subsection{defaults.spad}
-\subsubsection{FiniteLinearAggregateSort}
-++ This package exports 3 sorting algorithms which work over
-++ FiniteLinearAggregates.
-<<FiniteLinearAggregateSort>>=
-FiniteLinearAggregateSort(S, V): Exports == Implementation where
- S: Type
- V: FiniteLinearAggregate(S) with shallowlyMutable
-
- B ==> Boolean
- I ==> Integer
-
- Exports ==> with
- quickSort: ((S, S) -> B, V) -> V
- ++ quickSort(f, agg) sorts the aggregate agg with the ordering function
- ++ f using the quicksort algorithm.
- heapSort : ((S, S) -> B, V) -> V
- ++ heapSort(f, agg) sorts the aggregate agg with the ordering function
- ++ f using the heapsort algorithm.
- shellSort: ((S, S) -> B, V) -> V
- ++ shellSort(f, agg) sorts the aggregate agg with the ordering function
- ++ f using the shellSort algorithm.
-
- Implementation ==> add
- siftUp : ((S, S) -> B, V, I, I) -> Void
- partition: ((S, S) -> B, V, I, I, I) -> I
- QuickSort: ((S, S) -> B, V, I, I) -> V
-
- quickSort(l, r) == QuickSort(l, r, minIndex r, maxIndex r)
-
- siftUp(l, r, i, n) ==
- t := qelt(r, i)
- while (j := 2*i+1) < n repeat
- if (k := j+1) < n and l(qelt(r, j), qelt(r, k)) then j := k
- if l(t,qelt(r,j)) then
- qsetelt_!(r, i, qelt(r, j))
- qsetelt_!(r, j, t)
- i := j
- else leave
-
- heapSort(l, r) ==
- not zero? minIndex r => error "not implemented"
- n := (#r)::I
- for k in shift(n,-1) - 1 .. 0 by -1 repeat siftUp(l, r, k, n)
- for k in n-1 .. 1 by -1 repeat
- swap_!(r, 0, k)
- siftUp(l, r, 0, k)
- r
-
- partition(l, r, i, j, k) ==
- -- partition r[i..j] such that r.s <= r.k <= r.t
- x := qelt(r, k)
- t := qelt(r, i)
- qsetelt_!(r, k, qelt(r, j))
- while i < j repeat
- if l(x,t) then
- qsetelt_!(r, j, t)
- j := j-1
- t := qsetelt_!(r, i, qelt(r, j))
- else (i := i+1; t := qelt(r, i))
- qsetelt_!(r, j, x)
- j
-
- QuickSort(l, r, i, j) ==
- n := j - i
- if one? n and l(qelt(r, j), qelt(r, i)) then swap_!(r, i, j)
- n < 2 => return r
- -- for the moment split at the middle item
- k := partition(l, r, i, j, i + shift(n,-1))
- QuickSort(l, r, i, k - 1)
- QuickSort(l, r, k + 1, j)
-
- shellSort(l, r) ==
- m := minIndex r
- n := maxIndex r
- -- use Knuths gap sequence: 1,4,13,40,121,...
- g := 1
- while g <= (n-m) repeat g := 3*g+1
- g := g quo 3
- while g > 0 repeat
- for i in m+g..n repeat
- j := i-g
- while j >= m and l(qelt(r, j+g), qelt(r, j)) repeat
- swap_!(r,j,j+g)
- j := j-g
- g := g quo 3
- r
-
-
-@
-\subsection{e04agents.spad}
-\subsubsection{e04AgentsPackage}
-<<e04AgentsPackage>>=
-e04AgentsPackage(): E == I where
-
-++ Author: Brian Dupee
-++ Date Created: February 1996
-++ Date Last Updated: June 1996
-++ Basic Operations: simple? linear?, quadratic?, nonLinear?
-++ Description:
-++ \axiomType{e04AgentsPackage} is a package of numerical agents to be used
-++ to investigate attributes of an input function so as to decide the
-++ \axiomFun{measure} of an appropriate numerical optimization routine.
-
- E ==> with
-
- finiteBound:(LOCDF,DF) -> LDF
- ++ finiteBound(l,b) repaces all instances of an infinite entry in
- ++ \axiom{l} by a finite entry \axiom{b} or \axiom{-b}.
- sortConstraints:NOA -> NOA
- ++ sortConstraints(args) uses a simple bubblesort on the list of
- ++ constraints using the degree of the expression on which to sort.
- ++ Of course, it must match the bounds to the constraints.
- sumOfSquares:EDF -> Union(EDF,"failed")
- ++ sumOfSquares(f) returns either an expression for which the square is
- ++ the original function of "failed".
- splitLinear:EDF -> EDF
- ++ splitLinear(f) splits the linear part from an expression which it
- ++ returns.
- simpleBounds?:LEDF -> Boolean
- ++ simpleBounds?(l) returns true if the list of expressions l are
- ++ simple.
- linear?:LEDF -> Boolean
- ++ linear?(l) returns true if all the bounds l are either linear or
- ++ simple.
- linear?:EDF -> Boolean
- ++ linear?(e) tests if \axiom{e} is a linear function.
- linearMatrix:(LEDF, NNI) -> MDF
- ++ linearMatrix(l,n) returns a matrix of coefficients of the linear
- ++ functions in \axiom{l}. If l is empty, the matrix has at least one
- ++ row.
- linearPart:LEDF -> LEDF
- ++ linearPart(l) returns the list of linear functions of \axiom{l}.
- nonLinearPart:LEDF -> LEDF
- ++ nonLinearPart(l) returns the list of non-linear functions of \axiom{l}.
- quadratic?:EDF -> Boolean
- ++ quadratic?(e) tests if \axiom{e} is a quadratic function.
- variables:LSA -> LS
- ++ variables(args) returns the list of variables in \axiom{args.lfn}
- varList:(EDF,NNI) -> LS
- ++ varList(e,n) returns a list of \axiom{n} indexed variables with name
- ++ as in \axiom{e}.
- changeNameToObjf:(Symbol,Result) -> Result
- ++ changeNameToObjf(s,r) changes the name of item \axiom{s} in \axiom{r}
- ++ to objf.
- expenseOfEvaluation:LSA -> F
- ++ expenseOfEvaluation(o) returns the intensity value of the
- ++ cost of evaluating the input set of functions. This is in terms
- ++ of the number of ``operational units''. It returns a value
- ++ in the range [0,1].
- optAttributes:Union(noa:NOA,lsa:LSA) -> List String
- ++ optAttributes(o) is a function for supplying a list of attributes
- ++ of an optimization problem.
-
- I ==> add
-
- import ExpertSystemToolsPackage, ExpertSystemContinuityPackage
-
- sumOfSquares2:EFI -> Union(EFI,"failed")
- nonLinear?:EDF -> Boolean
- finiteBound2:(OCDF,DF) -> DF
- functionType:EDF -> String
-
- finiteBound2(a:OCDF,b:DF):DF ==
- not finite?(a) =>
- positive?(a) => b
- -b
- retract(a)@DF
-
- finiteBound(l:LOCDF,b:DF):LDF == [finiteBound2(i,b) for i in l]
-
- sortConstraints(args:NOA):NOA ==
- Args := copy args
- c:LEDF := Args.cf
- l:LOCDF := Args.lb
- u:LOCDF := Args.ub
- m:INT := (# c) - 1
- n:INT := (# l) - m
- for j in m..1 by -1 repeat
- for i in 1..j repeat
- s:EDF := c.i
- t:EDF := c.(i+1)
- if linear?(t) and (nonLinear?(s) or quadratic?(s)) then
- swap!(c,i,i+1)$LEDF
- swap!(l,n+i-1,n+i)$LOCDF
- swap!(u,n+i-1,n+i)$LOCDF
- Args
-
- changeNameToObjf(s:Symbol,r:Result):Result ==
- a := remove!(s,r)$Result
- a case Any =>
- insert!([objf@Symbol,a],r)$Result
- r
- r
-
- sum(a:EDF,b:EDF):EDF == a+b
-
- variables(args:LSA): LS == variables(reduce(sum,(args.lfn)))
-
- sumOfSquares(f:EDF):Union(EDF,"failed") ==
- e := edf2efi(f)
- s:Union(EFI,"failed") := sumOfSquares2(e)
- s case EFI =>
- map(fi2df,s)$EF2(FI,DF)
- "failed"
-
- sumOfSquares2(f:EFI):Union(EFI,"failed") ==
- p := retractIfCan(f)@Union(PFI,"failed")
- p case PFI =>
- r := squareFreePart(p)$PFI
- (p=r)@Boolean => "failed"
- tp := totalDegree(p)$PFI
- tr := totalDegree(r)$PFI
- t := tp quo tr
- found := false
- q := r
- for i in 2..t by 2 repeat
- s := q**2
- (s=p)@Boolean =>
- found := true
- leave
- q := r**i
- if found then
- q :: EFI
- else
- "failed"
- "failed"
-
- splitLinear(f:EDF):EDF ==
- out := 0$EDF
- (l := isPlus(f)$EDF) case LEDF =>
- for i in l repeat
- if not quadratic? i then
- out := out + i
- out
- out
-
- edf2pdf(f:EDF):PDF == (retract(f)@PDF)$EDF
-
- varList(e:EDF,n:NNI):LS ==
- s := name(first(variables(edf2pdf(e))$PDF)$LS)$Symbol
- [subscript(s,[t::OutputForm]) for t in expand([1..n])$Segment(Integer)]
-
- functionType(f:EDF):String ==
- n := #(variables(f))$EDF
- p := (retractIfCan(f)@Union(PDF,"failed"))$EDF
- p case PDF =>
- d := totalDegree(p)$PDF
- one?(n*d) => "simple"
- one?(d) => "linear"
- (d=2)@Boolean => "quadratic"
- "non-linear"
- "non-linear"
-
- simpleBounds?(l: LEDF):Boolean ==
- a := true
- for e in l repeat
- not (functionType(e) = "simple")@Boolean =>
- a := false
- leave
- a
-
- simple?(e:EDF):Boolean == (functionType(e) = "simple")@Boolean
-
- linear?(e:EDF):Boolean == (functionType(e) = "linear")@Boolean
-
- quadratic?(e:EDF):Boolean == (functionType(e) = "quadratic")@Boolean
-
- nonLinear?(e:EDF):Boolean == (functionType(e) = "non-linear")@Boolean
-
- linear?(l: LEDF):Boolean ==
- a := true
- for e in l repeat
- s := functionType(e)
- (s = "quadratic")@Boolean or (s = "non-linear")@Boolean =>
- a := false
- leave
- a
-
- simplePart(l:LEDF):LEDF == [i for i in l | simple?(i)]
-
- linearPart(l:LEDF):LEDF == [i for i in l | linear?(i)]
-
- nonLinearPart(l:LEDF):LEDF ==
- [i for i in l | not linear?(i) and not simple?(i)]
-
- linearMatrix(l:LEDF, n:NNI):MDF ==
- empty?(l) => mat([],n)
- L := linearPart l
- M := zero(max(1,# L)$NNI,n)$MDF
- vars := varList(first(l)$LEDF,n)
- row:INT := 1
- for a in L repeat
- for j in monomials(edf2pdf(a))$PDF repeat
- col:INT := 1
- for c in vars repeat
- if ((first(variables(j)$PDF)$LS)=c)@Boolean then
- M(row,col):= first(coefficients(j)$PDF)$LDF
- col := col+1
- row := row + 1
- M
-
- expenseOfEvaluation(o:LSA):F ==
- expenseOfEvaluation(vector(copy o.lfn)$VEDF)
-
- optAttributes(o:Union(noa:NOA,lsa:LSA)):List String ==
- o case noa =>
- n := o.noa
- s1:String := "The object function is " functionType(n.fn)
- if empty?(n.lb) then
- s2:String := "There are no bounds on the variables"
- else
- s2:String := "There are simple bounds on the variables"
- c := n.cf
- if empty?(c) then
- s3:String := "There are no constraint functions"
- else
- t := #(c)
- lin := #(linearPart(c))
- nonlin := #(nonLinearPart(c))
- s3:String := "There are " string(lin)$String " linear and "_
- string(nonlin)$String " non-linear constraints"
- [s1,s2,s3]
- l := o.lsa
- s:String := "non-linear"
- if linear?(l.lfn) then
- s := "linear"
- ["The object functions are " s]
-
-@
-\subsection{expexpan.spad}
-++ UnivariatePuiseuxSeriesWithExponentialSingularity is a domain used to
-++ represent functions with essential singularities. Objects in this
-++ domain are sums, where each term in the sum is a univariate Puiseux
-++ series times the exponential of a univariate Puiseux series. Thus,
-++ the elements of this domain are sums of expressions of the form
-++ \spad{g(x) * exp(f(x))}, where g(x) is a univariate Puiseux series
-++ and f(x) is a univariate Puiseux series with no terms of non-negative
-++ degree.
-\subsubsection{UnivariatePuiseuxSeriesWithExponentialSingularity}
-<<UnivariatePuiseuxSeriesWithExponentialSingularity>>=
-UnivariatePuiseuxSeriesWithExponentialSingularity(R,FE,var,cen):_
- Exports == Implementation where
- R : Join(OrderedSet,RetractableTo Integer,_
- LinearlyExplicitRingOver Integer,GcdDomain)
- FE : Join(AlgebraicallyClosedField,TranscendentalFunctionCategory,_
- FunctionSpace R)
- var : Symbol
- cen : FE
- B ==> Boolean
- I ==> Integer
- L ==> List
- RN ==> Fraction Integer
- UPXS ==> UnivariatePuiseuxSeries(FE,var,cen)
- EXPUPXS ==> ExponentialOfUnivariatePuiseuxSeries(FE,var,cen)
- OFE ==> OrderedCompletion FE
- Result ==> Union(OFE,"failed")
- PxRec ==> Record(k: Fraction Integer,c:FE)
- Term ==> Record(%coef:UPXS,%expon:EXPUPXS,%expTerms:List PxRec)
- -- the %expTerms field is used to record the list of the terms (a 'term'
- -- records an exponent and a coefficient) in the exponent %expon
- TypedTerm ==> Record(%term:Term,%type:String)
- -- a term together with a String which tells whether it has an infinite,
- -- zero, or unknown limit as var -> cen+
- TRec ==> Record(%zeroTerms: List Term,_
- %infiniteTerms: List Term,_
- %failedTerms: List Term,_
- %puiseuxSeries: UPXS)
- SIGNEF ==> ElementaryFunctionSign(R,FE)
-
- Exports ==> Join(FiniteAbelianMonoidRing(UPXS,EXPUPXS),IntegralDomain) with
- limitPlus : % -> Union(OFE,"failed")
- ++ limitPlus(f(var)) returns \spad{limit(var -> cen+,f(var))}.
- dominantTerm : % -> Union(TypedTerm,"failed")
- ++ dominantTerm(f(var)) returns the term that dominates the limiting
- ++ behavior of \spad{f(var)} as \spad{var -> cen+} together with a
- ++ \spadtype{String} which briefly describes that behavior. The
- ++ value of the \spadtype{String} will be \spad{"zero"} (resp.
- ++ \spad{"infinity"}) if the term tends to zero (resp. infinity)
- ++ exponentially and will \spad{"series"} if the term is a
- ++ Puiseux series.
-
- Implementation ==> PolynomialRing(UPXS,EXPUPXS) add
- makeTerm : (UPXS,EXPUPXS) -> Term
- coeff : Term -> UPXS
- exponent : Term -> EXPUPXS
- exponentTerms : Term -> List PxRec
- setExponentTerms_! : (Term,List PxRec) -> List PxRec
- computeExponentTerms_! : Term -> List PxRec
- terms : % -> List Term
- sortAndDiscardTerms: List Term -> TRec
- termsWithExtremeLeadingCoef : (L Term,RN,I) -> Union(L Term,"failed")
- filterByOrder: (L Term,(RN,RN) -> B) -> Record(%list:L Term,%order:RN)
- dominantTermOnList : (L Term,RN,I) -> Union(Term,"failed")
- iDominantTerm : L Term -> Union(Record(%term:Term,%type:String),"failed")
-
- retractIfCan f ==
- (numberOfMonomials f = 1) and (zero? degree f) => leadingCoefficient f
- "failed"
-
- recip f ==
- numberOfMonomials f = 1 =>
- monomial(inv leadingCoefficient f,- degree f)
- "failed"
-
- makeTerm(coef,expon) == [coef,expon,empty()]
- coeff term == term.%coef
- exponent term == term.%expon
- exponentTerms term == term.%expTerms
- setExponentTerms_!(term,list) == term.%expTerms := list
- computeExponentTerms_! term ==
- setExponentTerms_!(term,entries complete terms exponent term)
-
- terms f ==
- -- terms with a higher order singularity will appear closer to the
- -- beginning of the list because of the ordering in EXPPUPXS;
- -- no "expnonent terms" are computed by this function
- zero? f => empty()
- concat(makeTerm(leadingCoefficient f,degree f),terms reductum f)
-
- sortAndDiscardTerms termList ==
- -- 'termList' is the list of terms of some function f(var), ordered
- -- so that terms with a higher order singularity occur at the
- -- beginning of the list.
- -- This function returns lists of candidates for the "dominant
- -- term" in 'termList', i.e. the term which describes the
- -- asymptotic behavior of f(var) as var -> cen+.
- -- 'zeroTerms' will contain terms which tend to zero exponentially
- -- and contains only those terms with the lowest order singularity.
- -- 'zeroTerms' will be non-empty only when there are no terms of
- -- infinite or series type.
- -- 'infiniteTerms' will contain terms which tend to infinity
- -- exponentially and contains only those terms with the highest
- -- order singularity.
- -- 'failedTerms' will contain terms which have an exponential
- -- singularity, where we cannot say whether the limiting value
- -- is zero or infinity. Only terms with a higher order sigularity
- -- than the terms on 'infiniteList' are included.
- -- 'pSeries' will be a Puiseux series representing a term without an
- -- exponential singularity. 'pSeries' will be non-zero only when no
- -- other terms are known to tend to infinity exponentially
- zeroTerms : List Term := empty()
- infiniteTerms : List Term := empty()
- failedTerms : List Term := empty()
- -- we keep track of whether or not we've found an infinite term
- -- if so, 'infTermOrd' will be set to a negative value
- infTermOrd : RN := 0
- -- we keep track of whether or not we've found a zero term
- -- if so, 'zeroTermOrd' will be set to a negative value
- zeroTermOrd : RN := 0
- ord : RN := 0; pSeries : UPXS := 0 -- dummy values
- while not empty? termList repeat
- -- 'expon' is a Puiseux series
- expon := exponent(term := first termList)
- -- quit if there is an infinite term with a higher order singularity
- (ord := order(expon,0)) > infTermOrd => leave "infinite term dominates"
- -- if ord = 0, we've hit the end of the list
- (ord = 0) =>
- -- since we have a series term, don't bother with zero terms
- leave(pSeries := coeff(term); zeroTerms := empty())
- coef := coefficient(expon,ord)
- -- if we can't tell if the lowest order coefficient is positive or
- -- negative, we have a "failed term"
- (signum := sign(coef)$SIGNEF) case "failed" =>
- failedTerms := concat(term,failedTerms)
- termList := rest termList
- -- if the lowest order coefficient is positive, we have an
- -- "infinite term"
- (sig := signum :: Integer) = 1 =>
- infTermOrd := ord
- infiniteTerms := concat(term,infiniteTerms)
- -- since we have an infinite term, don't bother with zero terms
- zeroTerms := empty()
- termList := rest termList
- -- if the lowest order coefficient is negative, we have a
- -- "zero term" if there are no infinite terms and no failed
- -- terms, add the term to 'zeroTerms'
- if empty? infiniteTerms then
- zeroTerms :=
- ord = zeroTermOrd => concat(term,zeroTerms)
- zeroTermOrd := ord
- list term
- termList := rest termList
- -- reverse "failed terms" so that higher order singularities
- -- appear at the beginning of the list
- [zeroTerms,infiniteTerms,reverse_! failedTerms,pSeries]
-
- termsWithExtremeLeadingCoef(termList,ord,signum) ==
- -- 'termList' consists of terms of the form [g(x),exp(f(x)),...];
- -- when 'signum' is +1 (resp. -1), this function filters 'termList'
- -- leaving only those terms such that coefficient(f(x),ord) is
- -- maximal (resp. minimal)
- while (coefficient(exponent first termList,ord) = 0) repeat
- termList := rest termList
- empty? termList => error "UPXSSING: can't happen"
- coefExtreme := coefficient(exponent first termList,ord)
- outList := list first termList; termList := rest termList
- for term in termList repeat
- (coefDiff := coefficient(exponent term,ord) - coefExtreme) = 0 =>
- outList := concat(term,outList)
- (sig := sign(coefDiff)$SIGNEF) case "failed" => return "failed"
- (sig :: Integer) = signum => outList := list term
- outList
-
- filterByOrder(termList,predicate) ==
- -- 'termList' consists of terms of the form [g(x),exp(f(x)),expTerms],
- -- where 'expTerms' is a list containing some of the terms in the
- -- series f(x).
- -- The function filters 'termList' and, when 'predicate' is < (resp. >),
- -- leaves only those terms with the lowest (resp. highest) order term
- -- in 'expTerms'
- while empty? exponentTerms first termList repeat
- termList := rest termList
- empty? termList => error "UPXSING: can't happen"
- ordExtreme := (first exponentTerms first termList).k
- outList := list first termList
- for term in rest termList repeat
- not empty? exponentTerms term =>
- (ord := (first exponentTerms term).k) = ordExtreme =>
- outList := concat(term,outList)
- predicate(ord,ordExtreme) =>
- ordExtreme := ord
- outList := list term
- -- advance pointers on "exponent terms" on terms on 'outList'
- for term in outList repeat
- setExponentTerms_!(term,rest exponentTerms term)
- [outList,ordExtreme]
-
- dominantTermOnList(termList,ord0,signum) ==
- -- finds dominant term on 'termList'
- -- it is known that "exponent terms" of order < 'ord0' are
- -- the same for all terms on 'termList'
- newList := termsWithExtremeLeadingCoef(termList,ord0,signum)
- newList case "failed" => "failed"
- termList := newList :: List Term
- empty? rest termList => first termList
- filtered :=
- signum = 1 => filterByOrder(termList,#1 < #2)
- filterByOrder(termList,#1 > #2)
- termList := filtered.%list
- empty? rest termList => first termList
- dominantTermOnList(termList,filtered.%order,signum)
-
- iDominantTerm termList ==
- termRecord := sortAndDiscardTerms termList
- zeroTerms := termRecord.%zeroTerms
- infiniteTerms := termRecord.%infiniteTerms
- failedTerms := termRecord.%failedTerms
- pSeries := termRecord.%puiseuxSeries
- -- in future versions, we will deal with "failed terms"
- -- at present, if any occur, we cannot determine the limit
- not empty? failedTerms => "failed"
- not zero? pSeries => [makeTerm(pSeries,0),"series"]
- not empty? infiniteTerms =>
- empty? rest infiniteTerms => [first infiniteTerms,"infinity"]
- for term in infiniteTerms repeat computeExponentTerms_! term
- ord0 := order exponent first infiniteTerms
- (dTerm := dominantTermOnList(infiniteTerms,ord0,1)) case "failed" =>
- return "failed"
- [dTerm :: Term,"infinity"]
- empty? rest zeroTerms => [first zeroTerms,"zero"]
- for term in zeroTerms repeat computeExponentTerms_! term
- ord0 := order exponent first zeroTerms
- (dTerm := dominantTermOnList(zeroTerms,ord0,-1)) case "failed" =>
- return "failed"
- [dTerm :: Term,"zero"]
-
- dominantTerm f == iDominantTerm terms f
-
- limitPlus f ==
- -- list the terms occurring in 'f'; if there are none, then f = 0
- empty?(termList := terms f) => 0
- -- compute dominant term
- (tInfo := iDominantTerm termList) case "failed" => "failed"
- termInfo := tInfo :: Record(%term:Term,%type:String)
- domTerm := termInfo.%term
- (type := termInfo.%type) = "series" =>
- -- find limit of series term
- (ord := order(pSeries := coeff domTerm,1)) > 0 => 0
- coef := coefficient(pSeries,ord)
- member?(var,variables coef) => "failed"
- ord = 0 => coef :: OFE
- -- in the case of an infinite limit, we need to know the sign
- -- of the first non-zero coefficient
- (signum := sign(coef)$SIGNEF) case "failed" => "failed"
- (signum :: Integer) = 1 => plusInfinity()
- minusInfinity()
- type = "zero" => 0
- -- examine lowest order coefficient in series part of 'domTerm'
- ord := order(pSeries := coeff domTerm)
- coef := coefficient(pSeries,ord)
- member?(var,variables coef) => "failed"
- (signum := sign(coef)$SIGNEF) case "failed" => "failed"
- (signum :: Integer) = 1 => plusInfinity()
- minusInfinity()
-
-
-@
-\subsection{gbeuclid.spad}
-\subsubsection{EuclideanGroebnerBasisPackage}
-++ Description: \spadtype{EuclideanGroebnerBasisPackage} computes groebner
-++ bases for polynomial ideals over euclidean domains.
-++ The basic computation provides
-++ a distinguished set of generators for these ideals.
-++ This basis allows an easy test for membership: the operation
-++ \spadfun{euclideanNormalForm} returns zero on ideal members. The string
-++ "info" and "redcrit" can be given as additional args to provide
-++ incremental information during the computation. If "info" is given,
-++ a computational summary is given for each s-polynomial. If "redcrit"
-++ is given, the reduced critical pairs are printed. The term ordering
-++ is determined by the polynomial type used. Suggested types include
-++ \spadtype{DistributedMultivariatePolynomial},
-++ \spadtype{HomogeneousDistributedMultivariatePolynomial},
-++ \spadtype{GeneralDistributedMultivariatePolynomial}.
-<<EuclideanGroebnerBasisPackage>>=
-EuclideanGroebnerBasisPackage(Dom, Expon, VarSet, Dpol): T == C where
-
- Dom: EuclideanDomain
- Expon: OrderedAbelianMonoidSup
- VarSet: OrderedSet
- Dpol: PolynomialCategory(Dom, Expon, VarSet)
-
- T== with
-
- euclideanNormalForm: (Dpol, List(Dpol) ) -> Dpol
- ++ euclideanNormalForm(poly,gb) reduces the polynomial poly modulo the
- ++ precomputed groebner basis gb giving a canonical representative
- ++ of the residue class.
- euclideanGroebner: List(Dpol) -> List(Dpol)
- ++ euclideanGroebner(lp) computes a groebner basis for a polynomial ideal
- ++ over a euclidean domain generated by the list of polynomials lp.
- euclideanGroebner: (List(Dpol), String) -> List(Dpol)
- ++ euclideanGroebner(lp, infoflag) computes a groebner basis
- ++ for a polynomial ideal over a euclidean domain
- ++ generated by the list of polynomials lp.
- ++ During computation, additional information is printed out
- ++ if infoflag is given as
- ++ either "info" (for summary information) or
- ++ "redcrit" (for reduced critical pairs)
- euclideanGroebner: (List(Dpol), String, String ) -> List(Dpol)
- ++ euclideanGroebner(lp, "info", "redcrit") computes a groebner basis
- ++ for a polynomial ideal generated by the list of polynomials lp.
- ++ If the second argument is "info", a summary is given of the critical pairs.
- ++ If the third argument is "redcrit", critical pairs are printed.
- C== add
- Ex ==> OutputForm
- lc ==> leadingCoefficient
- red ==> reductum
-
- import OutputForm
-
- ------ Definition list of critPair
- ------ lcmfij is now lcm of headterm of poli and polj
- ------ lcmcij is now lcm of of lc poli and lc polj
-
- critPair ==>Record(lcmfij: Expon, lcmcij: Dom, poli:Dpol, polj: Dpol )
- Prinp ==> Record( ci:Dpol,tci:Integer,cj:Dpol,tcj:Integer,c:Dpol,
- tc:Integer,rc:Dpol,trc:Integer,tH:Integer,tD:Integer)
-
- ------ Definition of intermediate functions
-
- strongGbasis: (List(Dpol), Integer, Integer) -> List(Dpol)
- eminGbasis: List(Dpol) -> List(Dpol)
- ecritT: (critPair ) -> Boolean
- ecritM: (Expon, Dom, Expon, Dom) -> Boolean
- ecritB: (Expon, Dom, Expon, Dom, Expon, Dom) -> Boolean
- ecrithinH: (Dpol, List(Dpol)) -> Boolean
- ecritBonD: (Dpol, List(critPair)) -> List(critPair)
- ecritMTondd1:(List(critPair)) -> List(critPair)
- ecritMondd1:(Expon, Dom, List(critPair)) -> List(critPair)
- crithdelH: (Dpol, List(Dpol)) -> List(Dpol)
- eupdatF: (Dpol, List(Dpol) ) -> List(Dpol)
- updatH: (Dpol, List(Dpol), List(Dpol), List(Dpol) ) -> List(Dpol)
- sortin: (Dpol, List(Dpol) ) -> List(Dpol)
- eRed: (Dpol, List(Dpol), List(Dpol) ) -> Dpol
- ecredPol: (Dpol, List(Dpol) ) -> Dpol
- esPol: (critPair) -> Dpol
- updatD: (List(critPair), List(critPair)) -> List(critPair)
- lepol: Dpol -> Integer
- prinshINFO : Dpol -> Void
- prindINFO: (critPair, Dpol, Dpol,Integer,Integer,Integer) -> Integer
- prinpolINFO: List(Dpol) -> Void
- prinb: Integer -> Void
-
- ------ MAIN ALGORITHM GROEBNER ------------------------
- euclideanGroebner( Pol: List(Dpol) ) ==
- eminGbasis(strongGbasis(Pol,0,0))
-
- euclideanGroebner( Pol: List(Dpol), xx1: String) ==
- xx1 = "redcrit" =>
- eminGbasis(strongGbasis(Pol,1,0))
- xx1 = "info" =>
- eminGbasis(strongGbasis(Pol,2,1))
- print(" "::Ex)
- print("WARNING: options are - redcrit and/or info - "::Ex)
- print(" you didn't type them correct"::Ex)
- print(" please try again"::Ex)
- print(" "::Ex)
- []
-
- euclideanGroebner( Pol: List(Dpol), xx1: String, xx2: String) ==
- (xx1 = "redcrit" and xx2 = "info") or
- (xx1 = "info" and xx2 = "redcrit") =>
- eminGbasis(strongGbasis(Pol,1,1))
- xx1 = "redcrit" and xx2 = "redcrit" =>
- eminGbasis(strongGbasis(Pol,1,0))
- xx1 = "info" and xx2 = "info" =>
- eminGbasis(strongGbasis(Pol,2,1))
- print(" "::Ex)
- print("WARNING: options are - redcrit and/or info - "::Ex)
- print(" you didn't type them correct"::Ex)
- print(" please try again "::Ex)
- print(" "::Ex)
- []
-
- ------ calculate basis
-
- strongGbasis(Pol: List(Dpol),xx1: Integer, xx2: Integer ) ==
- dd1, D : List(critPair)
-
- --------- create D and Pol
-
- Pol1:= sort( (degree #1 > degree #2) or
- ((degree #1 = degree #2 ) and
- sizeLess?(leadingCoefficient #2,leadingCoefficient #1)),
- Pol)
- Pol:= [first(Pol1)]
- H:= Pol
- Pol1:= rest(Pol1)
- D:= nil
- while ^null Pol1 repeat
- h:= first(Pol1)
- Pol1:= rest(Pol1)
- en:= degree(h)
- lch:= lc h
- dd1:= [[sup(degree(x), en), lcm(leadingCoefficient x, lch), x, h]$critPair
- for x in Pol]
- D:= updatD(ecritMTondd1(sort((#1.lcmfij < #2.lcmfij) or
- (( #1.lcmfij = #2.lcmfij ) and
- ( sizeLess?(#1.lcmcij,#2.lcmcij)) ),
- dd1)), ecritBonD(h,D))
- Pol:= cons(h, eupdatF(h, Pol))
- ((en = degree(first(H))) and (leadingCoefficient(h) = leadingCoefficient(first(H)) ) ) =>
- " go to top of while "
- H:= updatH(h,H,crithdelH(h,H),[h])
- H:= sort((degree #1 > degree #2) or
- ((degree #1 = degree #2 ) and
- sizeLess?(leadingCoefficient #2,leadingCoefficient #1)), H)
- D:= sort((#1.lcmfij < #2.lcmfij) or
- (( #1.lcmfij = #2.lcmfij ) and
- ( sizeLess?(#1.lcmcij,#2.lcmcij)) ) ,D)
- xx:= xx2
-
- -------- loop
-
- while ^null D repeat
- D0:= first D
- ep:=esPol(D0)
- D:= rest(D)
- eh:= ecredPol(eRed(ep,H,H),H)
- if xx1 = 1 then
- prinshINFO(eh)
- eh = 0 =>
- if xx2 = 1 then
- ala:= prindINFO(D0,ep,eh,#H, #D, xx)
- xx:= 2
- " go to top of while "
- eh := unitCanonical eh
- e:= degree(eh)
- leh:= lc eh
- dd1:= [[sup(degree(x), e), lcm(leadingCoefficient x, leh), x, eh]$critPair
- for x in Pol]
- D:= updatD(ecritMTondd1(sort( (#1.lcmfij <
- #2.lcmfij) or (( #1.lcmfij = #2.lcmfij ) and
- ( sizeLess?(#1.lcmcij,#2.lcmcij)) ), dd1)), ecritBonD(eh,D))
- Pol:= cons(eh,eupdatF(eh,Pol))
- ^ecrithinH(eh,H) or
- ((e = degree(first(H))) and (leadingCoefficient(eh) = leadingCoefficient(first(H)) ) ) =>
- if xx2 = 1 then
- ala:= prindINFO(D0,ep,eh,#H, #D, xx)
- xx:= 2
- " go to top of while "
- H:= updatH(eh,H,crithdelH(eh,H),[eh])
- H:= sort( (degree #1 > degree #2) or
- ((degree #1 = degree #2 ) and
- sizeLess?(leadingCoefficient #2,leadingCoefficient #1)), H)
- if xx2 = 1 then
- ala:= prindINFO(D0,ep,eh,#H, #D, xx)
- xx:= 2
- " go to top of while "
- if xx2 = 1 then
- prinpolINFO(Pol)
- print(" THE GROEBNER BASIS over EUCLIDEAN DOMAIN"::Ex)
- if xx1 = 1 and xx2 ^= 1 then
- print(" THE GROEBNER BASIS over EUCLIDEAN DOMAIN"::Ex)
- H
-
- --------------------------------------
-
- --- erase multiple of e in D2 using crit M
-
- ecritMondd1(e: Expon, c: Dom, D2: List(critPair))==
- null D2 => nil
- x:= first(D2)
- ecritM(e,c, x.lcmfij, lcm(leadingCoefficient(x.poli), leadingCoefficient(x.polj)))
- => ecritMondd1(e, c, rest(D2))
- cons(x, ecritMondd1(e, c, rest(D2)))
-
- -------------------------------
-
- ecredPol(h: Dpol, F: List(Dpol) ) ==
- h0:Dpol:= 0
- null F => h
- while h ^= 0 repeat
- h0:= h0 + monomial(leadingCoefficient(h),degree(h))
- h:= eRed(red(h), F, F)
- h0
- ----------------------------
-
- --- reduce dd1 using crit T and crit M
-
- ecritMTondd1(dd1: List(critPair))==
- null dd1 => nil
- f1:= first(dd1)
- s1:= #(dd1)
- cT1:= ecritT(f1)
- s1= 1 and cT1 => nil
- s1= 1 => dd1
- e1:= f1.lcmfij
- r1:= rest(dd1)
- f2:= first(r1)
- e1 = f2.lcmfij and f1.lcmcij = f2.lcmcij =>
- cT1 => ecritMTondd1(cons(f1, rest(r1)))
- ecritMTondd1(r1)
- dd1 := ecritMondd1(e1, f1.lcmcij, r1)
- cT1 => ecritMTondd1(dd1)
- cons(f1, ecritMTondd1(dd1))
-
- -----------------------------
-
- --- erase elements in D fullfilling crit B
-
- ecritBonD(h:Dpol, D: List(critPair))==
- null D => nil
- x:= first(D)
- x1:= x.poli
- x2:= x.polj
- ecritB(degree(h), leadingCoefficient(h), degree(x1),leadingCoefficient(x1),degree(x2),leadingCoefficient(x2)) =>
- ecritBonD(h, rest(D))
- cons(x, ecritBonD(h, rest(D)))
-
- -----------------------------
-
- --- concat F and h and erase multiples of h in F
-
- eupdatF(h: Dpol, F: List(Dpol)) ==
- null F => nil
- f1:= first(F)
- ecritM(degree h, leadingCoefficient(h), degree f1, leadingCoefficient(f1))
- => eupdatF(h, rest(F))
- cons(f1, eupdatF(h, rest(F)))
-
- -----------------------------
- --- concat H and h and erase multiples of h in H
-
- updatH(h: Dpol, H: List(Dpol), Hh: List(Dpol), Hhh: List(Dpol)) ==
- null H => append(Hh,Hhh)
- h1:= first(H)
- hlcm:= sup(degree(h1), degree(h))
- plc:= extendedEuclidean(leadingCoefficient(h), leadingCoefficient(h1))
- hp:= monomial(plc.coef1,subtractIfCan(hlcm, degree(h))::Expon)*h +
- monomial(plc.coef2,subtractIfCan(hlcm, degree(h1))::Expon)*h1
- (ecrithinH(hp, Hh) and ecrithinH(hp, Hhh)) =>
- hpp:= append(rest(H),Hh)
- hp:= ecredPol(eRed(hp,hpp,hpp),hpp)
- updatH(h, rest(H), crithdelH(hp,Hh),cons(hp,crithdelH(hp,Hhh)))
- updatH(h, rest(H), Hh,Hhh)
-
- --------------------------------------------------
- ---- delete elements in cons(h,H)
-
- crithdelH(h: Dpol, H: List(Dpol))==
- null H => nil
- h1:= first(H)
- dh1:= degree h1
- dh:= degree h
- ecritM(dh, lc h, dh1, lc h1) => crithdelH(h, rest(H))
- dh1 = sup(dh,dh1) =>
- plc:= extendedEuclidean( lc h1, lc h)
- cons(plc.coef1*h1 + monomial(plc.coef2,subtractIfCan(dh1,dh)::Expon)*h,
- crithdelH(h,rest(H)))
- cons(h1, crithdelH(h,rest(H)))
-
- eminGbasis(F: List(Dpol)) ==
- null F => nil
- newbas := eminGbasis rest F
- cons(ecredPol( first(F), newbas),newbas)
-
- ------------------------------------------------
- --- does h belong to H
-
- ecrithinH(h: Dpol, H: List(Dpol))==
- null H => true
- h1:= first(H)
- ecritM(degree h1, lc h1, degree h, lc h) => false
- ecrithinH(h, rest(H))
-
- -----------------------------
- --- calculate euclidean S-polynomial of a critical pair
-
- esPol(p:critPair)==
- Tij := p.lcmfij
- fi := p.poli
- fj := p.polj
- lij:= lcm(leadingCoefficient(fi), leadingCoefficient(fj))
- red(fi)*monomial((lij exquo leadingCoefficient(fi))::Dom,
- subtractIfCan(Tij, degree fi)::Expon) -
- red(fj)*monomial((lij exquo leadingCoefficient(fj))::Dom,
- subtractIfCan(Tij, degree fj)::Expon)
-
- ----------------------------
-
- --- euclidean reduction mod F
-
- eRed(s: Dpol, H: List(Dpol), Hh: List(Dpol)) ==
- ( s = 0 or null H ) => s
- f1:= first(H)
- ds:= degree s
- lf1:= leadingCoefficient(f1)
- ls:= leadingCoefficient(s)
- e: Union(Expon, "failed")
- (((e:= subtractIfCan(ds, degree f1)) case "failed" ) or sizeLess?(ls, lf1) ) =>
- eRed(s, rest(H), Hh)
- sdf1:= divide(ls, lf1)
- q1:= sdf1.quotient
- sdf1.remainder = 0 =>
- eRed(red(s) - monomial(q1,e)*reductum(f1), Hh, Hh)
- eRed(s -(monomial(q1, e)*f1), rest(H), Hh)
-
- ----------------------------
-
- --- crit T true, if e1 and e2 are disjoint
-
- ecritT(p: critPair) ==
- pi:= p.poli
- pj:= p.polj
- ci:= lc pi
- cj:= lc pj
- (p.lcmfij = degree pi + degree pj) and (p.lcmcij = ci*cj)
-
- ----------------------------
-
- --- crit M - true, if lcm#2 multiple of lcm#1
-
- ecritM(e1: Expon, c1: Dom, e2: Expon, c2: Dom) ==
- en: Union(Expon, "failed")
- ((en:=subtractIfCan(e2, e1)) case "failed") or
- ((c2 exquo c1) case "failed") => false
- true
- ----------------------------
-
- --- crit B - true, if eik is a multiple of eh and eik ^equal
- --- lcm(eh,ei) and eik ^equal lcm(eh,ek)
-
- ecritB(eh:Expon, ch: Dom, ei:Expon, ci: Dom, ek:Expon, ck: Dom) ==
- eik:= sup(ei, ek)
- cik:= lcm(ci, ck)
- ecritM(eh, ch, eik, cik) and
- ^ecritM(eik, cik, sup(ei, eh), lcm(ci, ch)) and
- ^ecritM(eik, cik, sup(ek, eh), lcm(ck, ch))
-
- -------------------------------
-
- --- reduce p1 mod lp
-
- euclideanNormalForm(p1: Dpol, lp: List(Dpol))==
- eRed(p1, lp, lp)
-
- ---------------------------------
-
- --- insert element in sorted list
-
- sortin(p1: Dpol, lp: List(Dpol))==
- null lp => [p1]
- f1:= first(lp)
- elf1:= degree(f1)
- ep1:= degree(p1)
- ((elf1 < ep1) or ((elf1 = ep1) and
- sizeLess?(leadingCoefficient(f1),leadingCoefficient(p1)))) =>
- cons(f1,sortin(p1, rest(lp)))
- cons(p1,lp)
-
- updatD(D1: List(critPair), D2: List(critPair)) ==
- null D1 => D2
- null D2 => D1
- dl1:= first(D1)
- dl2:= first(D2)
- (dl1.lcmfij < dl2.lcmfij) => cons(dl1, updatD(D1.rest, D2))
- cons(dl2, updatD(D1, D2.rest))
-
- ---- calculate number of terms of polynomial
-
- lepol(p1:Dpol)==
- n: Integer
- n:= 0
- while p1 ^= 0 repeat
- n:= n + 1
- p1:= red(p1)
- n
-
- ---- print blanc lines
-
- prinb(n: Integer)==
- for i in 1..n repeat messagePrint(" ")
-
- ---- print reduced critpair polynom
-
- prinshINFO(h: Dpol)==
- prinb(2)
- messagePrint(" reduced Critpair - Polynom :")
- prinb(2)
- print(h::Ex)
- prinb(2)
-
- -------------------------------
-
- ---- print info string
-
- prindINFO(cp: critPair, ps: Dpol, ph: Dpol, i1:Integer,
- i2:Integer, n:Integer) ==
- ll: List Prinp
- a: Dom
- cpi:= cp.poli
- cpj:= cp.polj
- if n = 1 then
- prinb(1)
- messagePrint("you choose option -info- ")
- messagePrint("abbrev. for the following information strings are")
- messagePrint(" ci => Leading monomial for critpair calculation")
- messagePrint(" tci => Number of terms of polynomial i")
- messagePrint(" cj => Leading monomial for critpair calculation")
- messagePrint(" tcj => Number of terms of polynomial j")
- messagePrint(" c => Leading monomial of critpair polynomial")
- messagePrint(" tc => Number of terms of critpair polynomial")
- messagePrint(" rc => Leading monomial of redcritpair polynomial")
- messagePrint(" trc => Number of terms of redcritpair polynomial")
- messagePrint(" tF => Number of polynomials in reduction list F")
- messagePrint(" tD => Number of critpairs still to do")
- prinb(4)
- n:= 2
- prinb(1)
- a:= 1
- ph = 0 =>
- ps = 0 =>
- ll:= [[monomial(a,degree(cpi)),lepol(cpi),monomial(a,degree(cpj)),
- lepol(cpj),ps,0,ph,0,i1,i2]$Prinp]
- print(ll::Ex)
- prinb(1)
- n
- ll:= [[monomial(a,degree(cpi)),lepol(cpi),
- monomial(a,degree(cpj)),lepol(cpj),monomial(a,degree(ps)),
- lepol(ps), ph,0,i1,i2]$Prinp]
- print(ll::Ex)
- prinb(1)
- n
- ll:= [[monomial(a,degree(cpi)),lepol(cpi),
- monomial(a,degree(cpj)),lepol(cpj),monomial(a,degree(ps)),
- lepol(ps),monomial(a,degree(ph)),lepol(ph),i1,i2]$Prinp]
- print(ll::Ex)
- prinb(1)
- n
-
- -------------------------------
-
- ---- print the groebner basis polynomials
-
- prinpolINFO(pl: List(Dpol))==
- n:Integer
- n:= #pl
- prinb(1)
- n = 1 =>
- print(" There is 1 Groebner Basis Polynomial "::Ex)
- prinb(2)
- print(" There are "::Ex)
- prinb(1)
- print(n::Ex)
- prinb(1)
- print(" Groebner Basis Polynomials. "::Ex)
- prinb(2)
-
-@
-\subsection{kl.spad}
-\subsubsection{SortedCache}
-++ A sorted cache of a cachable set S is a dynamic structure that
-++ keeps the elements of S sorted and assigns an integer to each
-++ element of S once it is in the cache. This way, equality and ordering
-++ on S are tested directly on the integers associated with the elements
-++ of S, once they have been entered in the cache.
-<<SortedCache>>=
-SortedCache(S:CachableSet): Exports == Implementation where
- N ==> NonNegativeInteger
- DIFF ==> 1024
-
- Exports ==> with
- clearCache : () -> Void
- ++ clearCache() empties the cache.
- cache : () -> List S
- ++ cache() returns the current cache as a list.
- enterInCache: (S, S -> Boolean) -> S
- ++ enterInCache(x, f) enters x in the cache, calling \spad{f(y)} to
- ++ determine whether x is equal to y. It returns x with an integer
- ++ associated with it.
- enterInCache: (S, (S, S) -> Integer) -> S
- ++ enterInCache(x, f) enters x in the cache, calling \spad{f(x, y)} to
- ++ determine whether \spad{x < y (f(x,y) < 0), x = y (f(x,y) = 0)}, or
- ++ \spad{x > y (f(x,y) > 0)}.
- ++ It returns x with an integer associated with it.
-
- Implementation ==> add
- shiftCache : (List S, N) -> Void
- insertInCache: (List S, List S, S, N) -> S
-
- cach := [nil()]$Record(cche:List S)
-
- cache() == cach.cche
-
- shiftCache(l, n) ==
- for x in l repeat setPosition(x, n + position x)
- void
-
- clearCache() ==
- for x in cache repeat setPosition(x, 0)
- cach.cche := nil()
- void
-
- enterInCache(x:S, equal?:S -> Boolean) ==
- scan := cache()
- while not null scan repeat
- equal?(y := first scan) =>
- setPosition(x, position y)
- return y
- scan := rest scan
- setPosition(x, 1 + #cache())
- cach.cche := concat(cache(), x)
- x
-
- enterInCache(x:S, triage:(S, S) -> Integer) ==
- scan := cache()
- pos:N:= 0
- for i in 1..#scan repeat
- zero?(n := triage(x, y := first scan)) =>
- setPosition(x, position y)
- return y
- n<0 => return insertInCache(first(cache(),(i-1)::N),scan,x,pos)
- scan := rest scan
- pos := position y
- setPosition(x, pos + DIFF)
- cach.cche := concat(cache(), x)
- x
-
- insertInCache(before, after, x, pos) ==
- if ((pos+1) = position first after) then shiftCache(after, DIFF)
- setPosition(x, pos + (((position first after) - pos)::N quo 2))
- cach.cche := concat(before, concat(x, after))
- x
-
-@
-\subsection{list.spad}
-\subsubsection{IndexedList}
-++ \spadtype{IndexedList} is a basic implementation of the functions
-++ in \spadtype{ListAggregate}, often using functions in the underlying
-++ LISP system. The second parameter to the constructor (\spad{mn})
-++ is the beginning index of the list. That is, if \spad{l} is a
-++ list, then \spad{elt(l,mn)} is the first value. This constructor
-++ is probably best viewed as the implementation of singly-linked
-++ lists that are addressable by index rather than as a mere wrapper
-++ for LISP lists.
-<<IndexedList>>=
-IndexedList(S:Type, mn:Integer): ListAggregate S == add
- #x == LENGTH(x)$Lisp
- concat(s:S,x:%) == CONS(s,x)$Lisp
- eq?(x,y) == EQ(x,y)$Lisp
- first x == SPADfirst(x)$Lisp
- elt(x,"first") == SPADfirst(x)$Lisp
- empty() == NIL$Lisp
- empty? x == NULL(x)$Lisp
- rest x == CDR(x)$Lisp
- elt(x,"rest") == CDR(x)$Lisp
- setfirst_!(x,s) ==
- empty? x => error "Cannot update an empty list"
- Qfirst RPLACA(x,s)$Lisp
- setelt(x,"first",s) ==
- empty? x => error "Cannot update an empty list"
- Qfirst RPLACA(x,s)$Lisp
- setrest_!(x,y) ==
- empty? x => error "Cannot update an empty list"
- Qrest RPLACD(x,y)$Lisp
- setelt(x,"rest",y) ==
- empty? x => error "Cannot update an empty list"
- Qrest RPLACD(x,y)$Lisp
- construct l == l pretend %
- parts s == s pretend List S
- reverse_! x == NREVERSE(x)$Lisp
- reverse x == REVERSE(x)$Lisp
- minIndex x == mn
-
- rest(x, n) ==
- for i in 1..n repeat
- if Qnull x then error "index out of range"
- x := Qrest x
- x
-
- copy x ==
- y := empty()
- for i in 0.. while not Qnull x repeat
- if Qeq(i,cycleMax) and cyclic? x then error "cyclic list"
- y := Qcons(Qfirst x,y)
- x := Qrest x
- (NREVERSE(y)$Lisp)@%
-
- if S has SetCategory then
- coerce(x):OutputForm ==
- -- displays cycle with overbar over the cycle
- y := empty()$List(OutputForm)
- s := cycleEntry x
- while Qneq(x, s) repeat
- y := concat((first x)::OutputForm, y)
- x := rest x
- y := reverse_! y
- empty? s => bracket y
- -- cyclic case: z is cylic part
- z := list((first x)::OutputForm)
- while Qneq(s, rest x) repeat
- x := rest x
- z := concat((first x)::OutputForm, z)
- bracket concat_!(y, overbar commaSeparate reverse_! z)
-
- x = y ==
- Qeq(x,y) => true
- while not Qnull x and not Qnull y repeat
- Qfirst x ^=$S Qfirst y => return false
- x := Qrest x
- y := Qrest y
- Qnull x and Qnull y
-
- latex(x : %): String ==
- s : String := "\left["
- while not Qnull x repeat
- s := concat(s, latex(Qfirst x)$S)$String
- x := Qrest x
- if not Qnull x then s := concat(s, ", ")$String
- concat(s, " \right]")$String
-
- member?(s,x) ==
- while not Qnull x repeat
- if s = Qfirst x then return true else x := Qrest x
- false
-
- -- Lots of code from parts of AGGCAT, repeated here to
- -- get faster compilation
- concat_!(x:%,y:%) ==
- Qnull x =>
- Qnull y => x
- Qpush(first y,x)
- QRPLACD(x,rest y)$Lisp
- x
- z:=x
- while not Qnull Qrest z repeat
- z:=Qrest z
- QRPLACD(z,y)$Lisp
- x
-
- -- Then a quicky:
- if S has SetCategory then
- removeDuplicates_! l ==
- p := l
- while not Qnull p repeat
--- p := setrest_!(p, remove_!(#1 = Qfirst p, Qrest p))
--- far too expensive - builds closures etc.
- pp:=p
- f:S:=Qfirst p
- p:=Qrest p
- while not Qnull (pr:=Qrest pp) repeat
- if (Qfirst pr)@S = f then QRPLACD(pp,Qrest pr)$Lisp
- else pp:=pr
- l
-
- -- then sorting
- mergeSort: ((S, S) -> Boolean, %, Integer) -> %
-
- sort_!(f, l) == mergeSort(f, l, #l)
-
- merge_!(f, p, q) ==
- Qnull p => q
- Qnull q => p
- Qeq(p, q) => error "cannot merge a list into itself"
- if f(Qfirst p, Qfirst q)
- then (r := t := p; p := Qrest p)
- else (r := t := q; q := Qrest q)
- while not Qnull p and not Qnull q repeat
- if f(Qfirst p, Qfirst q)
- then (QRPLACD(t, p)$Lisp; t := p; p := Qrest p)
- else (QRPLACD(t, q)$Lisp; t := q; q := Qrest q)
- QRPLACD(t, if Qnull p then q else p)$Lisp
- r
-
- split_!(p, n) ==
- n < 1 => error "index out of range"
- p := rest(p, (n - 1)::NonNegativeInteger)
- q := Qrest p
- QRPLACD(p, NIL$Lisp)$Lisp
- q
-
- mergeSort(f, p, n) ==
- if n = 2 and f(first rest p, first p) then p := reverse_! p
- n < 3 => p
- l := (n quo 2)::NonNegativeInteger
- q := split_!(p, l)
- p := mergeSort(f, p, l)
- q := mergeSort(f, q, n - l)
- merge_!(f, p, q)
-
-@
-\subsubsection{List}
-++ \spadtype{List} implements singly-linked lists that are
-++ addressable by indices; the index of the first element
-++ is 1. In addition to the operations provided by
-++ \spadtype{IndexedList}, this constructor provides some
-++ LISP-like functions such as \spadfun{null} and \spadfun{cons}.
-<<List>>=
-List(S:Type): ListAggregate S with
- nil : () -> %
- ++ nil() returns the empty list.
- null : % -> Boolean
- ++ null(u) tests if list \spad{u} is the
- ++ empty list.
- cons : (S, %) -> %
- ++ cons(element,u) appends \spad{element} onto the front
- ++ of list \spad{u} and returns the new list. This new list
- ++ and the old one will share some structure.
- append : (%, %) -> %
- ++ append(u1,u2) appends the elements of list \spad{u1}
- ++ onto the front of list \spad{u2}. This new list
- ++ and \spad{u2} will share some structure.
- if S has SetCategory then
- setUnion : (%, %) -> %
- ++ setUnion(u1,u2) appends the two lists u1 and u2, then
- ++ removes all duplicates. The order of elements in the
- ++ resulting list is unspecified.
- setIntersection : (%, %) -> %
- ++ setIntersection(u1,u2) returns a list of the elements
- ++ that lists \spad{u1} and \spad{u2} have in common.
- ++ The order of elements in the resulting list is unspecified.
- setDifference : (%, %) -> %
- ++ setDifference(u1,u2) returns a list of the elements
- ++ of \spad{u1} that are not also in \spad{u2}.
- ++ The order of elements in the resulting list is unspecified.
- if S has OpenMath then OpenMath
-
- == IndexedList(S, LISTMININDEX) add
- nil() == NIL$Lisp
- null l == NULL(l)$Lisp
- cons(s, l) == CONS(s, l)$Lisp
- append(l:%, t:%) == APPEND(l, t)$Lisp
-
- if S has OpenMath then
- writeOMList(dev: OpenMathDevice, x: %): Void ==
- OMputApp(dev)
- OMputSymbol(dev, "list1", "list")
- -- The following didn't compile because the compiler isn't
- -- convinced that `xval' is a S. Duhhh! MCD.
- --for xval in x repeat
- -- OMwrite(dev, xval, false)
- while not null x repeat
- OMwrite(dev,first x,false)
- x := rest x
- OMputEndApp(dev)
-
- OMwrite(x: %): String ==
- s: String := ""
- sp := OM_-STRINGTOSTRINGPTR(s)$Lisp
- dev: OpenMathDevice := OMopenString(sp pretend String, OMencodingXML)
- OMputObject(dev)
- writeOMList(dev, x)
- OMputEndObject(dev)
- OMclose(dev)
- s := OM_-STRINGPTRTOSTRING(sp)$Lisp pretend String
- s
-
- OMwrite(x: %, wholeObj: Boolean): String ==
- s: String := ""
- sp := OM_-STRINGTOSTRINGPTR(s)$Lisp
- dev: OpenMathDevice := OMopenString(sp pretend String, OMencodingXML)
- if wholeObj then
- OMputObject(dev)
- writeOMList(dev, x)
- if wholeObj then
- OMputEndObject(dev)
- OMclose(dev)
- s := OM_-STRINGPTRTOSTRING(sp)$Lisp pretend String
- s
-
- OMwrite(dev: OpenMathDevice, x: %): Void ==
- OMputObject(dev)
- writeOMList(dev, x)
- OMputEndObject(dev)
-
- OMwrite(dev: OpenMathDevice, x: %, wholeObj: Boolean): Void ==
- if wholeObj then
- OMputObject(dev)
- writeOMList(dev, x)
- if wholeObj then
- OMputEndObject(dev)
-
- if S has SetCategory then
- setUnion(l1:%,l2:%) == removeDuplicates concat(l1,l2)
-
- setIntersection(l1:%,l2:%) ==
- u :% := empty()
- l1 := removeDuplicates l1
- while not empty? l1 repeat
- if member?(first l1,l2) then u := cons(first l1,u)
- l1 := rest l1
- u
-
- setDifference(l1:%,l2:%) ==
- l1 := removeDuplicates l1
- lu:% := empty()
- while not empty? l1 repeat
- l11:=l1.1
- if not member?(l11,l2) then lu := concat(l11,lu)
- l1 := rest l1
- lu
-
- if S has ConvertibleTo InputForm then
- convert(x:%):InputForm ==
- convert concat(convert("construct"::Symbol)@InputForm,
- [convert a for a in (x pretend List S)]$List(InputForm))
-
-
-@
-\subsection{perm.spad}
-\subsubsection{Permutation}
-++ Description: Permutation(S) implements the group of all bijections
-++ on a set S, which move only a finite number of points.
-++ A permutation is considered as a map from S into S. In particular
-++ multiplication is defined as composition of maps:
-++ {\em pi1 * pi2 = pi1 o pi2}.
-++ The internal representation of permuatations are two lists
-++ of equal length representing preimages and images.
-<<Permutation>>=
-Permutation(S:SetCategory): public == private where
-
- B ==> Boolean
- PI ==> PositiveInteger
- I ==> Integer
- L ==> List
- NNI ==> NonNegativeInteger
- V ==> Vector
- PT ==> Partition
- OUTFORM ==> OutputForm
- RECCYPE ==> Record(cycl: L L S, permut: %)
- RECPRIM ==> Record(preimage: L S, image : L S)
-
- public ==> PermutationCategory S with
-
- listRepresentation: % -> RECPRIM
- ++ listRepresentation(p) produces a representation {\em rep} of
- ++ the permutation p as a list of preimages and images, i.e
- ++ p maps {\em (rep.preimage).k} to {\em (rep.image).k} for all
- ++ indices k.
- coercePreimagesImages : List List S -> %
- ++ coercePreimagesImages(lls) coerces the representation {\em lls}
- ++ of a permutation as a list of preimages and images to a permutation.
- coerce : List List S -> %
- ++ coerce(lls) coerces a list of cycles {\em lls} to a
- ++ permutation, each cycle being a list with not
- ++ repetitions, is coerced to the permutation, which maps
- ++ {\em ls.i} to {\em ls.i+1}, indices modulo the length of the list,
- ++ then these permutations are mutiplied.
- ++ Error: if repetitions occur in one cycle.
- coerce : List S -> %
- ++ coerce(ls) coerces a cycle {\em ls}, i.e. a list with not
- ++ repetitions to a permutation, which maps {\em ls.i} to
- ++ {\em ls.i+1}, indices modulo the length of the list.
- ++ Error: if repetitions occur.
- coerceListOfPairs : List List S -> %
- ++ coerceListOfPairs(lls) coerces a list of pairs {\em lls} to a
- ++ permutation.
- ++ Error: if not consistent, i.e. the set of the first elements
- ++ coincides with the set of second elements.
- --coerce : % -> OUTFORM
- ++ coerce(p) generates output of the permutation p with domain
- ++ OutputForm.
- degree : % -> NonNegativeInteger
- ++ degree(p) retuns the number of points moved by the
- ++ permutation p.
- movedPoints : % -> Set S
- ++ movedPoints(p) returns the set of points moved by the permutation p.
- cyclePartition : % -> Partition
- ++ cyclePartition(p) returns the cycle structure of a permutation
- ++ p including cycles of length 1 only if S is finite.
- order : % -> NonNegativeInteger
- ++ order(p) returns the order of a permutation p as a group element.
- numberOfCycles : % -> NonNegativeInteger
- ++ numberOfCycles(p) returns the number of non-trivial cycles of
- ++ the permutation p.
- sign : % -> Integer
- ++ sign(p) returns the signum of the permutation p, +1 or -1.
- even? : % -> Boolean
- ++ even?(p) returns true if and only if p is an even permutation,
- ++ i.e. {\em sign(p)} is 1.
- odd? : % -> Boolean
- ++ odd?(p) returns true if and only if p is an odd permutation
- ++ i.e. {\em sign(p)} is {\em -1}.
- sort : L % -> L %
- ++ sort(lp) sorts a list of permutations {\em lp} according to
- ++ cycle structure first according to length of cycles,
- ++ second, if S has \spadtype{Finite} or S has
- ++ \spadtype{OrderedSet} according to lexicographical order of
- ++ entries in cycles of equal length.
- if S has Finite then
- fixedPoints : % -> Set S
- ++ fixedPoints(p) returns the points fixed by the permutation p.
- if S has IntegerNumberSystem or S has Finite then
- coerceImages : L S -> %
- ++ coerceImages(ls) coerces the list {\em ls} to a permutation
- ++ whose image is given by {\em ls} and the preimage is fixed
- ++ to be {\em [1,...,n]}.
- ++ Note: {coerceImages(ls)=coercePreimagesImages([1,...,n],ls)}.
-
- private ==> add
-
- -- representation of the object:
-
- Rep := V L S
-
- -- import of domains and packages
-
- import OutputForm
- import Vector List S
-
- -- variables
-
- p,q : %
- exp : I
-
- -- local functions first, signatures:
-
- smaller? : (S,S) -> B
- rotateCycle: L S -> L S
- coerceCycle: L L S -> %
- smallerCycle?: (L S, L S) -> B
- shorterCycle?:(L S, L S) -> B
- permord:(RECCYPE,RECCYPE) -> B
- coerceToCycle:(%,B) -> L L S
- duplicates?: L S -> B
-
- smaller?(a:S, b:S): B ==
- S has OrderedSet => a <$S b
- S has Finite => lookup a < lookup b
- false
-
- rotateCycle(cyc: L S): L S ==
- -- smallest element is put in first place
- -- doesn't change cycle if underlying set
- -- is not ordered or not finite.
- min:S := first cyc
- minpos:I := 1 -- 1 = minIndex cyc
- for i in 2..maxIndex cyc repeat
- if smaller?(cyc.i,min) then
- min := cyc.i
- minpos := i
- one? minpos => cyc
- concat(last(cyc,((#cyc-minpos+1)::NNI)),first(cyc,(minpos-1)::NNI))
-
- coerceCycle(lls : L L S): % ==
- perm : % := 1
- for lists in reverse lls repeat
- perm := cycle lists * perm
- perm
-
- smallerCycle?(cyca: L S, cycb: L S): B ==
- #cyca ^= #cycb =>
- #cyca < #cycb
- for i in cyca for j in cycb repeat
- i ^= j => return smaller?(i, j)
- false
-
- shorterCycle?(cyca: L S, cycb: L S): B ==
- #cyca < #cycb
-
- permord(pa: RECCYPE, pb : RECCYPE): B ==
- for i in pa.cycl for j in pb.cycl repeat
- i ^= j => return smallerCycle?(i, j)
- #pa.cycl < #pb.cycl
-
- coerceToCycle(p: %, doSorting?: B): L L S ==
- preim := p.1
- im := p.2
- cycles := nil()$(L L S)
- while not null preim repeat
- -- start next cycle
- firstEltInCycle: S := first preim
- nextCycle : L S := list firstEltInCycle
- preim := rest preim
- nextEltInCycle := first im
- im := rest im
- while nextEltInCycle ^= firstEltInCycle repeat
- nextCycle := cons(nextEltInCycle, nextCycle)
- i := position(nextEltInCycle, preim)
- preim := delete(preim,i)
- nextEltInCycle := im.i
- im := delete(im,i)
- nextCycle := reverse nextCycle
- -- check on 1-cycles, we don't list these
- if not null rest nextCycle then
- if doSorting? and (S has OrderedSet or S has Finite) then
- -- put smallest element in cycle first:
- nextCycle := rotateCycle nextCycle
- cycles := cons(nextCycle, cycles)
- not doSorting? => cycles
- -- sort cycles
- S has OrderedSet or S has Finite =>
- sort(smallerCycle?,cycles)$(L L S)
- sort(shorterCycle?,cycles)$(L L S)
-
- duplicates? (ls : L S ): B ==
- x := copy ls
- while not null x repeat
- member? (first x ,rest x) => return true
- x := rest x
- false
-
- -- now the exported functions
-
- listRepresentation p ==
- s : RECPRIM := [p.1,p.2]
-
- coercePreimagesImages preImageAndImage ==
- p : % := [preImageAndImage.1,preImageAndImage.2]
-
- movedPoints p == construct p.1 --check on fixed points !!
-
- degree p == #movedPoints p
-
- p = q ==
- #(preimp := p.1) ^= #(preimq := q.1) => false
- for i in 1..maxIndex preimp repeat
- pos := position(preimp.i, preimq)
- pos = 0 => return false
- (p.2).i ^= (q.2).pos => return false
- true
-
- orbit(p ,el) ==
- -- start with a 1-element list:
- out : Set S := brace list el
- el2 := eval(p, el)
- while el2 ^= el repeat
- -- be carefull: insert adds one element
- -- as side effect to out
- insert_!(el2, out)
- el2 := eval(p, el2)
- out
-
- cyclePartition p ==
- partition([#c for c in coerceToCycle(p, false)])$Partition
-
- order p ==
- ord: I := lcm removeDuplicates convert cyclePartition p
- ord::NNI
-
- sign(p) ==
- even? p => 1
- - 1
-
-
- even?(p) == even?(#(p.1) - numberOfCycles p)
- -- see the book of James and Kerber on symmetric groups
- -- for this formula.
-
- odd?(p) == odd?(#(p.1) - numberOfCycles p)
-
- pa < pb ==
- pacyc:= coerceToCycle(pa,true)
- pbcyc:= coerceToCycle(pb,true)
- for i in pacyc for j in pbcyc repeat
- i ^= j => return smallerCycle? ( i, j )
- maxIndex pacyc < maxIndex pbcyc
-
- coerce(lls : L L S): % == coerceCycle lls
-
- coerce(ls : L S): % == cycle ls
-
- sort(inList : L %): L % ==
- not (S has OrderedSet or S has Finite) => inList
- ownList: L RECCYPE := nil()$(L RECCYPE)
- for sigma in inList repeat
- ownList :=
- cons([coerceToCycle(sigma,true),sigma]::RECCYPE, ownList)
- ownList := sort(permord, ownList)$(L RECCYPE)
- outList := nil()$(L %)
- for rec in ownList repeat
- outList := cons(rec.permut, outList)
- reverse outList
-
- coerce (p: %): OUTFORM ==
- cycles: L L S := coerceToCycle(p,true)
- outfmL : L OUTFORM := nil()
- for cycle in cycles repeat
- outcycL: L OUTFORM := nil()
- for elt in cycle repeat
- outcycL := cons(elt :: OUTFORM, outcycL)
- outfmL := cons(paren blankSeparate reverse outcycL, outfmL)
- -- The identity element will be output as 1:
- null outfmL => outputForm(1@Integer)
- -- represent a single cycle in the form (a b c d)
- -- and not in the form ((a b c d)):
- null rest outfmL => first outfmL
- hconcat reverse outfmL
-
- cycles(vs ) == coerceCycle vs
-
- cycle(ls) ==
- #ls < 2 => 1
- duplicates? ls => error "cycle: the input contains duplicates"
- [ls, append(rest ls, list first ls)]
-
- coerceListOfPairs(loP) ==
- preim := nil()$(L S)
- im := nil()$(L S)
- for pair in loP repeat
- if first pair ^= second pair then
- preim := cons(first pair, preim)
- im := cons(second pair, im)
- duplicates?(preim) or duplicates?(im) or brace(preim)$(Set S) _
- ^= brace(im)$(Set S) =>
- error "coerceListOfPairs: the input cannot be interpreted as a permutation"
- [preim, im]
-
- q * p ==
- -- use vectors for efficiency??
- preimOfp : V S := construct p.1
- imOfp : V S := construct p.2
- preimOfq := q.1
- imOfq := q.2
- preimOfqp := nil()$(L S)
- imOfqp := nil()$(L S)
- -- 1 = minIndex preimOfp
- for i in 1..(maxIndex preimOfp) repeat
- -- find index of image of p.i in q if it exists
- j := position(imOfp.i, preimOfq)
- if j = 0 then
- -- it does not exist
- preimOfqp := cons(preimOfp.i, preimOfqp)
- imOfqp := cons(imOfp.i, imOfqp)
- else
- -- it exists
- el := imOfq.j
- -- if the composition fixes the element, we don't
- -- have to do anything
- if el ^= preimOfp.i then
- preimOfqp := cons(preimOfp.i, preimOfqp)
- imOfqp := cons(el, imOfqp)
- -- we drop the parts of q which have to do with p
- preimOfq := delete(preimOfq, j)
- imOfq := delete(imOfq, j)
- [append(preimOfqp, preimOfq), append(imOfqp, imOfq)]
-
- 1 == new(2,empty())$Rep
-
- inv p == [p.2, p.1]
-
- eval(p, el) ==
- pos := position(el, p.1)
- pos = 0 => el
- (p.2).pos
-
- elt(p, el) == eval(p, el)
-
- numberOfCycles p == #coerceToCycle(p, false)
-
-
- if S has IntegerNumberSystem then
-
- coerceImages (image) ==
- preImage : L S := [i::S for i in 1..maxIndex image]
- p : % := [preImage,image]
-
- if S has Finite then
-
- coerceImages (image) ==
- preImage : L S := [index(i::PI)::S for i in 1..maxIndex image]
- p : % := [preImage,image]
-
- fixedPoints ( p ) == complement movedPoints p
-
- cyclePartition p ==
- pt := partition([#c for c in coerceToCycle(p, false)])$Partition
- pt +$PT conjugate(partition([#fixedPoints(p)])$PT)$PT
-
-@
-\subsection{polset.spad}
-\subsubsection{PolynomialSetCategory}
-<<PolynomialSetCategory>>=
-PolynomialSetCategory(R:Ring, E:OrderedAbelianMonoidSup,_
- VarSet:OrderedSet, P:RecursivePolynomialCategory(R,E,VarSet)): Category ==
- Join(SetCategory,Collection(P),CoercibleTo(List(P))) with
- finiteAggregate
- retractIfCan : List(P) -> Union($,"failed")
- ++ \axiom{retractIfCan(lp)} returns an element of the domain whose elements
- ++ are the members of \axiom{lp} if such an element exists, otherwise
- ++ \axiom{"failed"} is returned.
- retract : List(P) -> $
- ++ \axiom{retract(lp)} returns an element of the domain whose elements
- ++ are the members of \axiom{lp} if such an element exists, otherwise
- ++ an error is produced.
- mvar : $ -> VarSet
- ++ \axiom{mvar(ps)} returns the main variable of the non constant polynomial
- ++ with the greatest main variable, if any, else an error is returned.
- variables : $ -> List VarSet
- ++ \axiom{variables(ps)} returns the decreasingly sorted list of the
- ++ variables which are variables of some polynomial in \axiom{ps}.
- mainVariables : $ -> List VarSet
- ++ \axiom{mainVariables(ps)} returns the decreasingly sorted list of the
- ++ variables which are main variables of some polynomial in \axiom{ps}.
- mainVariable? : (VarSet,$) -> Boolean
- ++ \axiom{mainVariable?(v,ps)} returns true iff \axiom{v} is the main variable
- ++ of some polynomial in \axiom{ps}.
- collectUnder : ($,VarSet) -> $
- ++ \axiom{collectUnder(ps,v)} returns the set consisting of the
- ++ polynomials of \axiom{ps} with main variable less than \axiom{v}.
- collect : ($,VarSet) -> $
- ++ \axiom{collect(ps,v)} returns the set consisting of the
- ++ polynomials of \axiom{ps} with \axiom{v} as main variable.
- collectUpper : ($,VarSet) -> $
- ++ \axiom{collectUpper(ps,v)} returns the set consisting of the
- ++ polynomials of \axiom{ps} with main variable greater than \axiom{v}.
- sort : ($,VarSet) -> Record(under:$,floor:$,upper:$)
- ++ \axiom{sort(v,ps)} returns \axiom{us,vs,ws} such that \axiom{us}
- ++ is \axiom{collectUnder(ps,v)}, \axiom{vs} is \axiom{collect(ps,v)}
- ++ and \axiom{ws} is \axiom{collectUpper(ps,v)}.
- trivialIdeal?: $ -> Boolean
- ++ \axiom{trivialIdeal?(ps)} returns true iff \axiom{ps} does
- ++ not contain non-zero elements.
- if R has IntegralDomain
- then
- roughBase? : $ -> Boolean
- ++ \axiom{roughBase?(ps)} returns true iff for every pair \axiom{{p,q}}
- ++ of polynomials in \axiom{ps} their leading monomials are
- ++ relatively prime.
- roughSubIdeal? : ($,$) -> Boolean
- ++ \axiom{roughSubIdeal?(ps1,ps2)} returns true iff it can proved
- ++ that all polynomials in \axiom{ps1} lie in the ideal generated by
- ++ \axiom{ps2} in \axiom{\axiom{(R)^(-1) P}} without computing Groebner bases.
- roughEqualIdeals? : ($,$) -> Boolean
- ++ \axiom{roughEqualIdeals?(ps1,ps2)} returns true iff it can
- ++ proved that \axiom{ps1} and \axiom{ps2} generate the same ideal
- ++ in \axiom{(R)^(-1) P} without computing Groebner bases.
- roughUnitIdeal? : $ -> Boolean
- ++ \axiom{roughUnitIdeal?(ps)} returns true iff \axiom{ps} contains some
- ++ non null element lying in the base ring \axiom{R}.
- headRemainder : (P,$) -> Record(num:P,den:R)
- ++ \axiom{headRemainder(a,ps)} returns \axiom{[b,r]} such that the leading
- ++ monomial of \axiom{b} is reduced in the sense of Groebner bases w.r.t.
- ++ \axiom{ps} and \axiom{r*a - b} lies in the ideal generated by \axiom{ps}.
- remainder : (P,$) -> Record(rnum:R,polnum:P,den:R)
- ++ \axiom{remainder(a,ps)} returns \axiom{[c,b,r]} such that \axiom{b} is fully
- ++ reduced in the sense of Groebner bases w.r.t. \axiom{ps},
- ++ \axiom{r*a - c*b} lies in the ideal generated by \axiom{ps}.
- ++ Furthermore, if \axiom{R} is a gcd-domain, \axiom{b} is primitive.
- rewriteIdealWithHeadRemainder : (List(P),$) -> List(P)
- ++ \axiom{rewriteIdealWithHeadRemainder(lp,cs)} returns \axiom{lr} such that
- ++ the leading monomial of every polynomial in \axiom{lr} is reduced
- ++ in the sense of Groebner bases w.r.t. \axiom{cs} and \axiom{(lp,cs)}
- ++ and \axiom{(lr,cs)} generate the same ideal in \axiom{(R)^(-1) P}.
- rewriteIdealWithRemainder : (List(P),$) -> List(P)
- ++ \axiom{rewriteIdealWithRemainder(lp,cs)} returns \axiom{lr} such that
- ++ every polynomial in \axiom{lr} is fully reduced in the sense
- ++ of Groebner bases w.r.t. \axiom{cs} and \axiom{(lp,cs)} and
- ++ \axiom{(lr,cs)} generate the same ideal in \axiom{(R)^(-1) P}.
- triangular? : $ -> Boolean
- ++ \axiom{triangular?(ps)} returns true iff \axiom{ps} is a triangular set,
- ++ i.e. two distinct polynomials have distinct main variables
- ++ and no constant lies in \axiom{ps}.
-
- add
-
- NNI ==> NonNegativeInteger
- B ==> Boolean
-
- elements: $ -> List(P)
-
- elements(ps:$):List(P) ==
- lp : List(P) := members(ps)$$
-
- variables1(lp:List(P)):(List VarSet) ==
- lvars : List(List(VarSet)) := [variables(p)$P for p in lp]
- sort(#1 > #2, removeDuplicates(concat(lvars)$List(VarSet)))
-
- variables2(lp:List(P)):(List VarSet) ==
- lvars : List(VarSet) := [mvar(p)$P for p in lp]
- sort(#1 > #2, removeDuplicates(lvars)$List(VarSet))
-
- variables (ps:$) ==
- variables1(elements(ps))
-
- mainVariables (ps:$) ==
- variables2(remove(ground?,elements(ps)))
-
- mainVariable? (v,ps) ==
- lp : List(P) := remove(ground?,elements(ps))
- while (not empty? lp) and (not (mvar(first(lp)) = v)) repeat
- lp := rest lp
- (not empty? lp)
-
- collectUnder (ps,v) ==
- lp : List P := elements(ps)
- lq : List P := []
- while (not empty? lp) repeat
- p := first lp
- lp := rest lp
- if (ground?(p)) or (mvar(p) < v)
- then
- lq := cons(p,lq)
- construct(lq)$$
-
- collectUpper (ps,v) ==
- lp : List P := elements(ps)
- lq : List P := []
- while (not empty? lp) repeat
- p := first lp
- lp := rest lp
- if (not ground?(p)) and (mvar(p) > v)
- then
- lq := cons(p,lq)
- construct(lq)$$
-
- collect (ps,v) ==
- lp : List P := elements(ps)
- lq : List P := []
- while (not empty? lp) repeat
- p := first lp
- lp := rest lp
- if (not ground?(p)) and (mvar(p) = v)
- then
- lq := cons(p,lq)
- construct(lq)$$
-
- sort (ps,v) ==
- lp : List P := elements(ps)
- us : List P := []
- vs : List P := []
- ws : List P := []
- while (not empty? lp) repeat
- p := first lp
- lp := rest lp
- if (ground?(p)) or (mvar(p) < v)
- then
- us := cons(p,us)
- else
- if (mvar(p) = v)
- then
- vs := cons(p,vs)
- else
- ws := cons(p,ws)
- [construct(us)$$,construct(vs)$$,construct(ws)$$]$Record(under:$,floor:$,upper:$)
-
- ps1 = ps2 ==
- {p for p in elements(ps1)} =$(Set P) {p for p in elements(ps2)}
-
- exactQuo : (R,R) -> R
-
- localInf? (p:P,q:P):B ==
- degree(p) <$E degree(q)
-
- localTriangular? (lp:List(P)):B ==
- lp := remove(zero?, lp)
- empty? lp => true
- any? (ground?, lp) => false
- lp := sort(mvar(#1)$P > mvar(#2)$P, lp)
- p,q : P
- p := first lp
- lp := rest lp
- while (not empty? lp) and (mvar(p) > mvar((q := first(lp)))) repeat
- p := q
- lp := rest lp
- empty? lp
-
- triangular? ps ==
- localTriangular? elements ps
-
- trivialIdeal? ps ==
- empty?(remove(zero?,elements(ps))$(List(P)))$(List(P))
-
- if R has IntegralDomain
- then
-
- roughUnitIdeal? ps ==
- any?(ground?,remove(zero?,elements(ps))$(List(P)))$(List P)
-
- relativelyPrimeLeadingMonomials? (p:P,q:P):B ==
- dp : E := degree(p)
- dq : E := degree(q)
- (sup(dp,dq)$E =$E dp +$E dq)@B
-
- roughBase? ps ==
- lp := remove(zero?,elements(ps))$(List(P))
- empty? lp => true
- rB? : B := true
- while (not empty? lp) and rB? repeat
- p := first lp
- lp := rest lp
- copylp := lp
- while (not empty? copylp) and rB? repeat
- rB? := relativelyPrimeLeadingMonomials?(p,first(copylp))
- copylp := rest copylp
- rB?
-
- roughSubIdeal?(ps1,ps2) ==
- lp: List(P) := rewriteIdealWithRemainder(elements(ps1),ps2)
- empty? (remove(zero?,lp))
-
- roughEqualIdeals? (ps1,ps2) ==
- ps1 =$$ ps2 => true
- roughSubIdeal?(ps1,ps2) and roughSubIdeal?(ps2,ps1)
-
- if (R has GcdDomain) and (VarSet has ConvertibleTo (Symbol))
- then
-
- LPR ==> List Polynomial R
- LS ==> List Symbol
-
- if R has EuclideanDomain
- then
- exactQuo(r:R,s:R):R ==
- r quo$R s
- else
- exactQuo(r:R,s:R):R ==
- (r exquo$R s)::R
-
- headRemainder (a,ps) ==
- lp1 : List(P) := remove(zero?, elements(ps))$(List(P))
- empty? lp1 => [a,1$R]
- any?(ground?,lp1) => [reductum(a),1$R]
- r : R := 1$R
- lp1 := sort(localInf?, reverse elements(ps))
- lp2 := lp1
- e : Union(E, "failed")
- while (not zero? a) and (not empty? lp2) repeat
- p := first lp2
- if ((e:= subtractIfCan(degree(a),degree(p))) case E)
- then
- g := gcd((lca := leadingCoefficient(a)),(lcp := leadingCoefficient(p)))$R
- (lca,lcp) := (exactQuo(lca,g),exactQuo(lcp,g))
- a := lcp * reductum(a) - monomial(lca, e::E)$P * reductum(p)
- r := r * lcp
- lp2 := lp1
- else
- lp2 := rest lp2
- [a,r]
-
- makeIrreducible! (frac:Record(num:P,den:R)):Record(num:P,den:R) ==
- g := gcd(frac.den,frac.num)$P
- one? g => frac
- frac.num := exactQuotient!(frac.num,g)
- frac.den := exactQuo(frac.den,g)
- frac
-
- remainder (a,ps) ==
- hRa := makeIrreducible! headRemainder (a,ps)
- a := hRa.num
- r : R := hRa.den
- zero? a => [1$R,a,r]
- b : P := monomial(1$R,degree(a))$P
- c : R := leadingCoefficient(a)
- while not zero?(a := reductum a) repeat
- hRa := makeIrreducible! headRemainder (a,ps)
- a := hRa.num
- r := r * hRa.den
- g := gcd(c,(lca := leadingCoefficient(a)))$R
- b := ((hRa.den) * exactQuo(c,g)) * b + monomial(exactQuo(lca,g),degree(a))$P
- c := g
- [c,b,r]
-
- rewriteIdealWithHeadRemainder(ps,cs) ==
- trivialIdeal? cs => ps
- roughUnitIdeal? cs => [0$P]
- ps := remove(zero?,ps)
- empty? ps => ps
- any?(ground?,ps) => [1$P]
- rs : List P := []
- while not empty? ps repeat
- p := first ps
- ps := rest ps
- p := (headRemainder(p,cs)).num
- if not zero? p
- then
- if ground? p
- then
- ps := []
- rs := [1$P]
- else
- primitivePart! p
- rs := cons(p,rs)
- removeDuplicates rs
-
- rewriteIdealWithRemainder(ps,cs) ==
- trivialIdeal? cs => ps
- roughUnitIdeal? cs => [0$P]
- ps := remove(zero?,ps)
- empty? ps => ps
- any?(ground?,ps) => [1$P]
- rs : List P := []
- while not empty? ps repeat
- p := first ps
- ps := rest ps
- p := (remainder(p,cs)).polnum
- if not zero? p
- then
- if ground? p
- then
- ps := []
- rs := [1$P]
- else
- rs := cons(unitCanonical(p),rs)
- removeDuplicates rs
-
-@
-\subsection{sortpak.spad}
-\subsubsection{SortPackage}
-++ This package exports sorting algorithnms
-<<SortPackage>>=
-SortPackage(S,A) : Exports == Implementation where
- S: Type
- A: IndexedAggregate(Integer,S)
- with (finiteAggregate; shallowlyMutable)
-
- Exports == with
- bubbleSort_!: (A,(S,S) -> Boolean) -> A
- ++ bubbleSort!(a,f) \undocumented
- insertionSort_!: (A, (S,S) -> Boolean) -> A
- ++ insertionSort!(a,f) \undocumented
- if S has OrderedSet then
- bubbleSort_!: A -> A
- ++ bubbleSort!(a) \undocumented
- insertionSort_!: A -> A
- ++ insertionSort! \undocumented
-
- Implementation == add
- bubbleSort_!(m,f) ==
- n := #m
- for i in 1..(n-1) repeat
- for j in n..(i+1) by -1 repeat
- if f(m.j,m.(j-1)) then swap_!(m,j,j-1)
- m
- insertionSort_!(m,f) ==
- for i in 2..#m repeat
- j := i
- while j > 1 and f(m.j,m.(j-1)) repeat
- swap_!(m,j,j-1)
- j := (j - 1) pretend PositiveInteger
- m
- if S has OrderedSet then
- bubbleSort_!(m) == bubbleSort_!(m,_<$S)
- insertionSort_!(m) == insertionSort_!(m,_<$S)
- if A has UnaryRecursiveAggregate(S) then
- bubbleSort_!(m,fn) ==
- empty? m => m
- l := m
- while not empty? (r := l.rest) repeat
- r := bubbleSort_!(r,fn)
- x := l.first
- if fn(r.first,x) then
- l.first := r.first
- r.first := x
- l.rest := r
- l := l.rest
- m
-
-@
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} {\bf PseudoRemainderSequence in prs.spad}
-\end{thebibliography}
-\end{document}