|
|
|
last edited 16 years ago by Mark Clements |
| 1 2 | ||
|
Editor: Mark Clements
Time: 2009/04/26 20:09:07 GMT-7 |
||
| Note: First draft | ||
changed: - The following shows Newton's method for numerically solving f(x)=0. It is also shows examples of calling Axiom expressions and Spad functions from Lisp. First, define Newton's method using the Axiom interpreter: \begin{axiom} -- Axiom interpreter function for Newton's algorithm R ==> Float I ==> Integer newton(f:Expression R,x:Symbol,x0:R):R == dfdx:Expression R := D(f,x) xt:R := x0 fxt:R := subst(f,x=xt) iterNum:I := 0 maxIt:I := 100 repeat xt := xt - fxt/subst(dfdx,x=xt) fxt := subst(f,x=xt) if abs(fxt)<1.0e-10 then return xt iterNum:=iterNum+1::I if iterNum >= maxIt then error "Maximum iterations exceeded." newton(x**2-2.0,x,2.0) newton(y**2-2.0,y,2.0) newton(x**2-2.0,x,2.0)-sqrt(2.0) \end{axiom} Second, we can also do this by calling the Newton method implemented in Lisp. We initially define/hack a Spad package which creates a Lisp function from an interpreter expression. \begin{spad} )lisp (defun |lambdaFuncallSpad| (f) (lambda (x) (funcall f x nil))) )abbrev package MKULF MakeUnaryLispFunction ++ Tools for making compiled lisp functions from top-level expressions ++ Author: Mark Clements ++ (based on the MakeUnaryCompiledFunction package by Manuel Bronstein) ++ Date Created: 20 April 2008 ++ Date Last Updated: 20 April 2008 ++ Description: transforms top-level objects into lisp functions. MakeUnaryLispFunction(S, D, I): Exports == Implementation where S: ConvertibleTo InputForm D, I: Type SY ==> Symbol DI ==> devaluate(D -> I)$Lisp Exports ==> with compiledFunction: (S, SY) -> SY ++ compiledFunction(expr, x) returns a function lisp{f: D -> I} ++ defined by lisp{(defun f (x) expr)}. ++ Function f is compiled and directly ++ applicable to objects of type D (in lisp). Implementation ==> add import MakeFunction(S) compiledFunction(e:S, x:SY) == t := [convert([devaluate(D)$Lisp]$List(InputForm)) ]$List(InputForm) lambdaFuncallSpad(compile(function(e, declare DI, x), t))$Lisp \end{spad} Then we can use this in Axiom... \begin{axiom} -- define Newton in Lisp )lisp (defun newton (f dfdx x0 &optional (tol 1.0d-10)) (let ((xt x0) (fxt (funcall f x0)) (maxit 100) (iternum 0)) (loop (setf xt (- xt (/ fxt (funcall dfdx xt)))) (setf fxt (funcall f xt)) (if (< (abs fxt) tol) (return xt)) (incf iternum) (if (>= iternum maxit) (error "Maximum iterations exceeded."))))) -- Spad->Lisp function translation compiledDF(expr: EXPR FLOAT, x: Symbol):Symbol == compiledFunction(expr,x)$MakeUnaryLispFunction(EXPR FLOAT,DFLOAT,DFLOAT) -- a short function to call the Lisp code newtonUsingLisp(f:Expression Float,x:Symbol,x0:DFLOAT):DFLOAT == float(NEWTON(compiledDF(f,x),compiledDF(D(f,x),x),x0)$Lisp) newtonUsingLisp(x**2-2.0,x,2.0::SF)-sqrt(2.0::SF) \end{axiom} Third, we can call a compiled Spad function in Lisp. Defining some example functions in Spad: \begin{spad} )abbrev package TESTP TestPackage R ==> DoubleFloat TestPackage: with f:R -> R dfdx:R -> R == add f(x) == x*x - 2.0::R dfdx(x) == 2*x \end{spad} and then calling those functions in Lisp from Axiom: \begin{axiom} )lisp (defun |lispFunctionFromSpad| (f dom args) (let ((spadf (|getFunctionFromDomain| f (list dom) args))) (lambda (x) (spadcall x spadf)))) float(NEWTON(lispFunctionFromSpad(f,'TestPackage,['DoubleFloat])$Lisp, lispFunctionFromSpad(dfdx,'TestPackage,['DoubleFloat])$Lisp,2::SF)$Lisp)-sqrt(2.0::SF) \end{axiom}
The following shows Newton's method for numerically solving f(x)=0. It is also shows examples of calling Axiom expressions and Spad functions from Lisp.
First, define Newton's method using the Axiom interpreter:
-- Axiom interpreter function for Newton's algorithm R ==> Float
I ==> Integer
newton(f:Expression R,x:Symbol,x0:R):R ==
dfdx:Expression R := D(f,x)
xt:R := x0
fxt:R := subst(f,x=xt)
iterNum:I := 0
maxIt:I := 100
repeat
xt := xt - fxt/subst(dfdx,x=xt)
fxt := subst(f,x=xt)
if abs(fxt)<1.0e-10 then return xt
iterNum:=iterNum+1::I
if iterNum >= maxIt then
error "Maximum iterations exceeded."
Function declaration newton : (Expression Float,Symbol,Float) ->
Float has been added to workspace.
newton(x**2-2.0,x,2.0)
Compiling function newton with type (Expression Float,Symbol,Float)
-> Float| (1) |
newton(y**2-2.0,y,2.0)
| (2) |
newton(x**2-2.0,x,2.0)-sqrt(2.0)
| (3) |
Second, we can also do this by calling the Newton method implemented in Lisp. We initially define/hack a Spad package which creates a Lisp function from an interpreter expression.
)lisp (defun |lambdaFuncallSpad| (f) (lambda (x) (funcall f x nil))) )abbrev package MKULF MakeUnaryLispFunction ++ Tools for making compiled lisp functions from top-level expressions ++ Author: Mark Clements ++ (based on the MakeUnaryCompiledFunction package by Manuel Bronstein) ++ Date Created: 20 April 2008 ++ Date Last Updated: 20 April 2008 ++ Description: transforms top-level objects into lisp functions. MakeUnaryLispFunction(S, D, I): Exports == Implementation where S: ConvertibleTo InputForm D, I: Type
SY ==> Symbol DI ==> devaluate(D -> I)$Lisp
Exports ==> with compiledFunction: (S, SY) -> SY ++ compiledFunction(expr, x) returns a function lisp{f: D -> I} ++ defined by lisp{(defun f (x) expr)}. ++ Function f is compiled and directly ++ applicable to objects of type D (in lisp).
Implementation ==> add import MakeFunction(S)
compiledFunction(e:S, x:SY) == t := [convert([devaluate(D)$Lisp]$List(InputForm)) ]$List(InputForm) lambdaFuncallSpad(compile(function(e, declare DI, x), t))$Lisp
Compiling FriCAS source code from file
/var/zope2/var/LatexWiki/1657093691659194492-25px002.spad using
old system compiler.
Value = |lambdaFuncallSpad|
MKULF abbreviates package MakeUnaryLispFunction
processing macro definition SY ==> Symbol
processing macro definition DI ==> (elt Lisp devaluate) D -> I
processing macro definition Exports ==> -- the constructor category
processing macro definition Implementation ==> -- the constructor capsule
------------------------------------------------------------------------
initializing NRLIB MKULF for MakeUnaryLispFunction
compiling into NRLIB MKULF
importing MakeFunction S
compiling exported compiledFunction : (S,Symbol) -> Symbol
Time: 0.05 SEC.
(time taken in buildFunctor: 0)
;;; *** |MakeUnaryLispFunction| REDEFINED
;;; *** |MakeUnaryLispFunction| REDEFINED
Time: 0 SEC.
Cumulative Statistics for Constructor MakeUnaryLispFunction
Time: 0.05 seconds
finalizing NRLIB MKULF
Processing MakeUnaryLispFunction for Browser database:
--------(compiledFunction (SY S SY))---------
--------constructor---------
------------------------------------------------------------------------
MakeUnaryLispFunction is now explicitly exposed in frame initial
MakeUnaryLispFunction will be automatically loaded when needed from
/var/zope2/var/LatexWiki/MKULF.NRLIB/codeThen we can use this in Axiom...
-- define Newton in Lisp
)lisp (defun newton (f dfdx x0 &optional (tol 1.0d-10)) (let ((xt x0) (fxt (funcall f x0)) (maxit 100) (iternum 0)) (loop (setf xt (- xt (/ fxt (funcall dfdx xt)))) (setf fxt (funcall f xt)) (if (< (abs fxt) tol) (return xt)) (incf iternum) (if (>= iternum maxit) (error "Maximum iterations exceeded.")))))
Value = NEWTON -- Spad->Lisp function translation compiledDF(expr: EXPR FLOAT, x: Symbol):Symbol == compiledFunction(expr,x)$MakeUnaryLispFunction(EXPR FLOAT,DFLOAT,DFLOAT)
Function declaration compiledDF : (Expression Float,Symbol) -> Symbol has been added to workspace.
-- a short function to call the Lisp code
newtonUsingLisp(f:Expression Float,x:Symbol,x0:DFLOAT):DFLOAT ==
float(NEWTON(compiledDF(f,x),compiledDF(D(f,x),x),x0)$Lisp)
Function declaration newtonUsingLisp : (Expression Float,Symbol,
DoubleFloat) -> DoubleFloat has been added to workspace.
newtonUsingLisp(x**2-2.0,x,2.0::SF)-sqrt(2.0::SF)
Compiling function compiledDF with type (Expression Float,Symbol)
-> SymbolCompiling function newtonUsingLisp with type (Expression Float,
Symbol,DoubleFloat) -> DoubleFloatCompiling function %A with type DoubleFloat -> DoubleFloat
Compiling function %B with type DoubleFloat -> DoubleFloat
| (4) |
Third, we can call a compiled Spad function in Lisp. Defining some example functions in Spad:
)abbrev package TESTP TestPackage
R ==> DoubleFloat
TestPackage: with
f:R -> R
dfdx:R -> R
== add
f(x) == x*x - 2.0::R
dfdx(x) == 2*x
Compiling FriCAS source code from file
/var/zope2/var/LatexWiki/2983317606354902709-25px004.spad using
old system compiler.
TESTP abbreviates package TestPackage
processing macro definition R ==> DoubleFloat
------------------------------------------------------------------------
initializing NRLIB TESTP for TestPackage
compiling into NRLIB TESTP
compiling exported f : DoubleFloat -> DoubleFloat
Time: 0.01 SEC.
compiling exported dfdx : DoubleFloat -> DoubleFloat
Time: 0.01 SEC.
(time taken in buildFunctor: 0)
;;; *** |TestPackage| REDEFINED
;;; *** |TestPackage| REDEFINED
Time: 0 SEC.
Cumulative Statistics for Constructor TestPackage
Time: 0.02 seconds
finalizing NRLIB TESTP
Processing TestPackage for Browser database:
--->-->TestPackage((f (R R))): Not documented!!!!
--->-->TestPackage((dfdx (R R))): Not documented!!!!
--->-->TestPackage(constructor): Not documented!!!!
--->-->TestPackage(): Missing Description
------------------------------------------------------------------------
TestPackage is now explicitly exposed in frame initial
TestPackage will be automatically loaded when needed from
/var/zope2/var/LatexWiki/TESTP.NRLIB/codeand then calling those functions in Lisp from Axiom:
)lisp (defun |lispFunctionFromSpad| (f dom args) (let ((spadf (|getFunctionFromDomain| f (list dom) args))) (lambda (x) (spadcall x spadf))))
Value = |lispFunctionFromSpad| float(NEWTON(lispFunctionFromSpad(f,'TestPackage,['DoubleFloat])$Lisp, lispFunctionFromSpad(dfdx,'TestPackage,['DoubleFloat])$Lisp,2::SF )$Lisp)-sqrt(2.0::SF)
| (5) |