incr-set prlevel 1
if #0>=3 START
incr-set prlevel -1
;;; Usage:
;;;     <push_forward f M N 
;;;
;;; Computes the pushforward N = f_*(M) over the current ring S, 
;;; (M regarded as a module via f)
;;; where f is a map from the current ring to the base ring of M.
incr-set prlevel 1
jump END
;;; Parameters:
;;;		f = 1xn matrix over a ring R, 
;;;         whose entries have degrees
;;;	        proportional to the degrees of the current ring.
;;;		M = R-module
;;; Output values:
;;;	    N = module over the current ring, S.
;;;	        If M is not finite via S, then the script 
;;;         outputs the codimension
;;;         of M/(vars of S)M (this is = dim R 
;;;         iff M is finite) and exits.
;;;
;;; The script first checks to see whether M will be a
;;; finitely generated module over the current ring via f.
;;;
;;; Assuming that it is,
;;; the push forward f_* M is computed.  This is done
;;; by first finding a presentation for M 
;;; in terms of a set of elements
;;; which generate M as an S-module over the ring 
;;; R \tensor S, and then
;;; calling push_forward1.
;;;
;;; Caveats:
;;; The script returns a set of relations of N that usually isn't
;;; minimal; of course one can then do an std or nres or... to
;;; find a minimal set of relations (the generators returned
;;; are minimal generators of N.)
;;;
;;;    There ought to be an optional maxdegree parameter, as in subring and pushforward1.
;;; One wouldn't even need to check for finite generation if it were set.
;Created 4/5/89 by D. Eisenbud
START:
;get a handle to the current ring:
<getvars @curring

;Find the dimension of the ring R:
setring #2
<getvars @oldvars
ncols @oldvars @dimension

;Find an R-presentation for M in terms of a set of S-generators:
tensor #1 #2 @M
std @M @M

;check that M is finite over S:
codim @M @codimension
if @codimension-@dimension easyout

;The following would crash if M were not finite over S!
k-basis @M @M
	;
	;

modulo @M #2 @M

setring @curring
<push_forward1 #1 @M #3

jump endplay

easyout:
incr-set prlevel -10
;The module is not finite over the new ring.
;Try a different map.
;The codimension is only
type @codimension
incr-set prlevel 10

endplay:

kill @oldvars @dimension @M @codimension @curring
END:
incr-set prlevel -1

$;;;;;;;; EXAMPLE SECTION ;;;;;;;;;;;;;;;;;;;;;;;;;
;Illustration of the Auslander-Buchsbaum formula:
;pd M = depth R - depth M.
;If we push M forward by a map f such that
;M is finitely generated via f,
;then the depth of M does not change, so 
;the projective dimension goes down:
;Also, if the projection is linear, 
;the degree stays the same.  Of course
;the number of generators generally goes up.

reset
<ring 6 a-z r6

;A module of projective dimension 2:
<generic_mat a 2 3 m
res m mm

<ring 5 a-z r5

<ring 4 a-z r4

;Amap from r5 to r6
imap g r5 r6
a a+b+c+d+e+f
	;
type g

;A generic projection map from r4 to r5
setring r5
<random_mat 1 4 r5 f
type f

setring r5
<push_forward
<push_forward g m p
<prune p p
res p pp

setring r4
<push_forward f p q
res q qq

type m
betti mm
degree mm.1
type p
betti pp
degree pp.1
type q
betti qq
degree qq.1

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Generic projection of the homogeneous coordinate ring of the
;twisted cubic into the plane.  The result is the normalization
;of the ideal of the nodal cubic:
reset

;Projective 3-space and 2-space:
<ring 4 a-z P3
<ring 3 a-z P2

;The ideal of the twisted cubic: 
setring P3
cat a m
	0 1
	0 1 2
wedge m 2 i

;A generic projection 
<random_mat 1 3 P3 f

setring P2
<push_forward f i j

;The result is not the ring of a subscheme of the plane:
betti j
;But it is an algebra of genus 0, degree 3 (it's the same homogeneous
;coordinate ring of the twisted cubic):
std j j
hilb j
; codimension = 1
; degree      = 3
; genus       = 0

;The support is a cubic (genus 1) in the plane -- nodal, of course:
<annihilator j k
betti k
std k k
hilb k
; codimension = 1
; degree      = 3
; genus       = 1
