home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
MAGAZINE
/
DDJ9309.ZIP
/
1993-SEP.ZIP
/
JACAL.ASC
< prev
next >
Wrap
Text File
|
1993-07-26
|
6KB
|
165 lines
_ALGEBRA AND THE LAMBDA CALCULUS_
by Aubrey Jaffer
LISTING ONE:
;;; Excerpt from Jacal: Symbolic Mathematics System, written in Scheme.
;;; Copyright 1989-1993 Aubrey Jaffer. See the file "COPYING" in
;;; the Jacal distribution for terms applying to this program.
;;;; Variable elimination
(define (poly:elim poleqns vars)
(cond (math:trace
(display-diag "eliminating:")
(newline-diag)
(write-sexp (math->sexp (map var->expl vars)) *output-grammar*)
(display-diag " from:")
(newline-diag)
(write-sexp (math->sexp (poleqns->licits poleqns)) *output-grammar*)))
(do ((vs vars (cdr vs)) (polys poleqns) (poly #f))
((null? vs)
(cond (math:trace
(display-diag "yielding:")
(newline-diag)
(write-sexp (math->sexp polys) *output-grammar*)))
polys)
(do ((var (car vs))
(pl polys (if (null? pl)
(math-error "not enough equations" poleqns vars)
(cdr pl)))
(npl '() (cons (car pl) npl)))
((poly:find-var? (car pl) var)
(set! poly (promote var (car pl)))
(do ((pls (cdr pl) (cdr pls)))
((null? pls) (set! polys npl))
(if (bunch? (car pls)) (math-error "elim bunch?" (car pls)))
(set! npl (cons (poly:resultant poly (car pls) var)
npl))))
(if (bunch? (car pl)) (math-error "elim bunch?" (car pl))))))
(define (infinite-list-of . elts)
(let ((lst (copy-list elts)))
(nconc lst lst)))
;;; This tries to solve the equations no matter what is involved.
;;; It will eliminate variables in vectors of equations.
(define (eliminate eqns vars)
(bunch:norm
(if (some bunch? eqns)
(apply map
(lambda arglist (eliminate arglist vars))
(map (lambda (x)
(if (bunch? x) x (infinite-list-of x)))
eqns))
(poly:elim eqns vars))))
(define (elim:test)
(define a (sexp->var 'A))
(define x (sexp->var 'X))
(define y (sexp->var 'Y))
(test (list (list a 0 0 124 81 11 3 45))
poly:elim
(list (list y (list x (list a 0 0 2) (list a 0 1)) 1)
(list y (list x (list a 5 1) 0 -1) 0 1)
(list y (list x (list a -1 3) 5) -1))
(list x y)))
(define (bunch:map proc b)
(cond ((bunch? b) (map (lambda (x) (bunch:map proc x)) b))
(else (proc b))))
(define (licits:for-each proc b)
(cond ((bunch? b) (for-each (lambda (x) (licits:for-each proc x)) b))
((eqn? b) (proc (eqn->poly b)))
(else (proc b))))
(define (licits:map proc b)
(cond ((bunch? b) (map (lambda (x) (licits:map proc x)) b))
((eqn? b) (poleqn->licit (proc (eqn->poly b))))
(else (proc b))))
(define (implicits:map proc b)
(cond ((bunch? b) (map (lambda (x) (implicits:map proc x)) b))
((eqn? b) (poleqn->licit (proc (eqn->poly b))))
((expl? b) (proc (expl->impl b)))
(else (proc b))))
;;; replaces each var in poly with (proc var).
;;; Used for substitutions in clambda and capply.
(define (poly:do-vars proc poly)
(if (number? poly) poly
(univ:demote (cons (proc (car poly))
(map (lambda (b) (poly:do-vars proc b))
(cdr poly))))))
(define (licits:do-vars proc licit)
(licits:map (lambda (poly) (poly:do-vars proc poly))
licit))
;;;; Canonical Lambda
;;;; This needs to handle algebraic extensions as well.
(define (clambda symlist body)
(let ((num-new-vars (length (remove-if lambdavar? symlist))))
(licits:do-vars
(lambda (var)
(let ((pos (position (var:nodiffs var) symlist)))
(cond (pos (lambda-var (+ 1 pos) (var:diff-depth var)))
((lambdavar? var) (bump-lambda-var var num-new-vars))
((lambdavarext? var) (bump-lambda-ext))
(else var))))
body)))
(define (clambda? cexp)
(cond ((number? cexp) #f)
((matrix? cexp) (some (lambda (row) (some clambda? row)) cexp))
((expr? cexp) (poly:find-var-if? cexp lambdavardep?))
((eqn? cexp) (poly:find-var-if? (eqn->poly cexp) lambdavardep?))
(else #f)))
;;;In order to keep the lambda application hygenic (in case a function
;;;of a function is called), we need to substitute occurences of
;;;lambda variables in the body with shadowed versions of the
;;;variables before we eliminate them. See:
;;; Technical Report No. 194
;;; Hygenic Macro Expansion
;;; E.E.Kohlbecker, D.P.Friedman, M.Fellinson, and B.Duba
;;; Indiana University
;;; May, 1986
;;;currently capply puts the structure of the clambda inside the
;;;structure of the arguments.
(define (capply body larglist)
(let* ((arglist (licits->poleqns larglist))
(arglist-length (length arglist))
(svlist '()) (dargs '())
(sbody
(licits:do-vars
(lambda (var)
(cond
((lambdavar? var)
(let ((lshf (- (min-lambda-position var) arglist-length)))
(cond ((< 0 lshf) (bump-lambda-var var (- arglist-length)))
(else (set! var (var:shadow var))
(set! svlist (adjoin var svlist))
var))))
((not (lambdavarext? var)) var)
;; must be some sort of extension
((radicalvar? var) var)))
body)))
(set! dargs (diffargs svlist arglist))
(implicits:map (lambda (p) (eliminate (cons p dargs) svlist)) sbody)))
(define (bump-lambda-var var delta)
(lambda-var (+ (lambda-position var) delta) (var:diff-depth var)))
(define (diffargs vlist args)
(map (lambda (var)
(bunch:map (lambda (e)
(univ:demote (cons var (cdr (licit->poleqn e)))))
(diffarg var args)))
vlist))
(define (diffarg var args)
(cond ((var:differential? var)
(total-differential (diffarg (var:undiff var) args)))
(else (list-ref args (- (lambda-position var) 1)))))