login  home  contents  what's new  discussion  bug reports     help  links  subscribe  changes  refresh  edit

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
-- Axiom interpreter function for Newton's algorithm
R ==> Float
Type: Void
axiom
I ==> Integer
Type: Void
axiom
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.
Type: Void
axiom
newton(x**2-2.0,x,2.0)
axiom
Compiling function newton with type (Expression(Float),Symbol,Float)
       -> Float

\label{eq1}1.4142135623746899106(1)
Type: Float
axiom
newton(y**2-2.0,y,2.0)

\label{eq2}1.4142135623746899106(2)
Type: Float
axiom
newton(x**2-2.0,x,2.0)-sqrt(2.0)

\label{eq3}0.15948618 E - 11(3)
Type: Float

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.

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
spad
   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.07 SEC.
(time taken in buildFunctor: 0)
;;; *** |MakeUnaryLispFunction| REDEFINED
;;; *** |MakeUnaryLispFunction| REDEFINED Time: 0.01 SEC.
Cumulative Statistics for Constructor MakeUnaryLispFunction Time: 0.08 seconds
finalizing NRLIB MKULF Processing MakeUnaryLispFunction for Browser database: --------(compiledFunction (SY S SY))--------- --------constructor--------- ; compiling file "/var/zope2/var/LatexWiki/MKULF.NRLIB/MKULF.lsp" (written 25 NOV 2010 04:58:06 PM): ; compiling (/VERSIONCHECK 2) ; compiling (DEFUN |MKULF;compiledFunction;S2S;1| ...) ; compiling (DEFUN |MakeUnaryLispFunction| ...) ; compiling (DEFUN |MakeUnaryLispFunction;| ...) ; compiling (MAKEPROP (QUOTE |MakeUnaryLispFunction|) ...)
; /var/zope2/var/LatexWiki/MKULF.NRLIB/MKULF.fasl written ; compilation finished in 0:00:00.102 ------------------------------------------------------------------------ MakeUnaryLispFunction is now explicitly exposed in frame initial MakeUnaryLispFunction will be automatically loaded when needed from /var/zope2/var/LatexWiki/MKULF.NRLIB/MKULF

Then we can use this in Axiom...

axiom
-- define Newton in Lisp
axiom
)lisp (defun newton (f dfdx x0 &optional (tol 1.0d-10) (maxit 100)) (let ((xt x0) (fxt
(funcall f x0)) (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.
Type: Void
axiom
-- 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.
Type: Void
axiom
newtonUsingLisp(x**2-2.0,x,2.0::SF)-sqrt(2.0::SF)
axiom
Compiling function compiledDF with type (Expression(Float),Symbol)
       -> Symbol
axiom
Compiling function newtonUsingLisp with type (Expression(Float),
      Symbol,DoubleFloat) -> DoubleFloat
axiom
Compiling function %A with type DoubleFloat -> DoubleFloat
axiom
Compiling function %B with type DoubleFloat -> DoubleFloat

\label{eq4}1.5947243525715749 e - 12(4)
Type: DoubleFloat

Third, we can call a compiled Spad function in Lisp. Defining some example functions in Spad:

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
spad
   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.03 SEC.
compiling exported dfdx : DoubleFloat -> DoubleFloat Time: 0.02 SEC.
(time taken in buildFunctor: 0)
;;; *** |TestPackage| REDEFINED
;;; *** |TestPackage| REDEFINED Time: 0 SEC.
Cumulative Statistics for Constructor TestPackage Time: 0.05 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 ; compiling file "/var/zope2/var/LatexWiki/TESTP.NRLIB/TESTP.lsp" (written 25 NOV 2010 04:58:07 PM): ; compiling (/VERSIONCHECK 2) ; compiling (DEFUN |TESTP;f;2Df;1| ...) ; compiling (DEFUN |TESTP;dfdx;2Df;2| ...) ; compiling (DEFUN |TestPackage| ...) ; compiling (DEFUN |TestPackage;| ...) ; compiling (MAKEPROP (QUOTE |TestPackage|) ...) ; compiling (MAKEPROP (QUOTE |TestPackage|) ...)
; /var/zope2/var/LatexWiki/TESTP.NRLIB/TESTP.fasl written ; compilation finished in 0:00:00.151 ------------------------------------------------------------------------ TestPackage is now explicitly exposed in frame initial TestPackage will be automatically loaded when needed from /var/zope2/var/LatexWiki/TESTP.NRLIB/TESTP

and then calling those functions in Lisp from Axiom:

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)

\label{eq5}1.5947243525715749 e - 12(5)
Type: DoubleFloat

Finally, within a Spad package, it is even easier to call a function through Lisp:

spad
-- the following approach is due to Waldek Hebisch
)lisp (defun |mkLispFunction1| (f) (lambda (x) (SPADCALL x f)))
)abbrev package TESTP TestPackage
R ==> DoubleFloat
I ==> Integer
TestPackage: with
    newton:(R->R,R->R,R,R,I)->R
    newton:(R->R,R->R,R)->R
  == add
    newton(f,dfdx,x0,tol,maxit) ==
         NEWTON(mkLispFunction1(f@(R -> R))$Lisp,
                 mkLispFunction1(dfdx@(R -> R))$Lisp,
                 x0,tol,maxit)$Lisp
    newton(f,dfdx,x0) == newton(f,dfdx,x0,1.0e-10::R,100::I)
spad
   Compiling FriCAS source code from file 
      /var/zope2/var/LatexWiki/5566883931090623725-25px006.spad using 
      old system compiler.
Value = |mkLispFunction1|
   TESTP abbreviates package TestPackage 
   processing macro definition R ==> DoubleFloat 
processing macro definition I ==> Integer
------------------------------------------------------------------------ initializing NRLIB TESTP for TestPackage compiling into NRLIB TESTP compiling exported newton : (DoubleFloat -> DoubleFloat,DoubleFloat -> DoubleFloat,DoubleFloat,DoubleFloat,Integer) -> DoubleFloat Time: 0.03 SEC.
compiling exported newton : (DoubleFloat -> DoubleFloat,DoubleFloat -> DoubleFloat,DoubleFloat) -> DoubleFloat Time: 0.02 SEC.
(time taken in buildFunctor: 0)
;;; *** |TestPackage| REDEFINED
;;; *** |TestPackage| REDEFINED Time: 0 SEC.
Cumulative Statistics for Constructor TestPackage Time: 0.05 seconds
finalizing NRLIB TESTP Processing TestPackage for Browser database: --->/var/zope2/var/LatexWiki/2983317606354902709-25px004.spad-->TestPackage((newton (R (Mapping R R) (Mapping R R) R R I))): Not documented!!!! --->/var/zope2/var/LatexWiki/2983317606354902709-25px004.spad-->TestPackage((newton (R (Mapping R R) (Mapping R R) R))): Not documented!!!! --->/var/zope2/var/LatexWiki/2983317606354902709-25px004.spad-->TestPackage(constructor): Not documented!!!! --->/var/zope2/var/LatexWiki/2983317606354902709-25px004.spad-->TestPackage(): Missing Description ; compiling file "/var/zope2/var/LatexWiki/TESTP.NRLIB/TESTP.lsp" (written 25 NOV 2010 04:58:08 PM): ; compiling (/VERSIONCHECK 2) ; compiling (DEFUN |TESTP;newton;2M2DfIDf;1| ...) ; compiling (DEFUN |TESTP;newton;2M2Df;2| ...) ; compiling (DEFUN |TestPackage| ...) ; compiling (DEFUN |TestPackage;| ...) ; compiling (MAKEPROP (QUOTE |TestPackage|) ...) ; compiling (MAKEPROP (QUOTE |TestPackage|) ...)
; /var/zope2/var/LatexWiki/TESTP.NRLIB/TESTP.fasl written ; compilation finished in 0:00:00.055 ------------------------------------------------------------------------ TestPackage is already explicitly exposed in frame initial TestPackage will be automatically loaded when needed from /var/zope2/var/LatexWiki/TESTP.NRLIB/TESTP

then

axiom
R ==> DoubleFloat
Type: Void
axiom
newton((x:R):R +-> x**2-2.0::R,(x:R):R +->
2.0::R*x,3.0::SF,1.0e-15,100)$TestPackage-sqrt(2.0)

\label{eq6}0.0(6)
Type: DoubleFloat
axiom
newtonExpression(f,x,x0) ==
        dfdx := D(f,x)
        newton((xt:R):R +-> eval(f,x,xt), (xt:R):R +-> eval(dfdx,x,xt),
x0)$TestPackage
Type: Void
axiom
newtonExpression(x**2-2.0,x,2.0)-sqrt(2.0)
axiom
Compiling function newtonExpression with type (Polynomial(Float),
      Variable(x),Float) -> DoubleFloat

\label{eq7}1.5949463971764999 e - 12(7)
Type: DoubleFloat




  Subject:   Be Bold !!
  ( 14 subscribers )  
Please rate this page: