\documentclass{article}
\usepackage{open-axiom}
\begin{document}
\title{\$SPAD/src/algebra e04Package.spad}
\author{Brian Dupee}
\maketitle
\begin{abstract}
\end{abstract}
\eject
\tableofcontents
\eject
\section{package OPTPACK AnnaNumericalOptimizationPackage}
<<package OPTPACK AnnaNumericalOptimizationPackage>>=
)abbrev package OPTPACK AnnaNumericalOptimizationPackage
++ Author: Brian Dupee
++ Date Created: February 1995
++ Date Last Updated: December 1997
++ Basic Operations: measure, optimize, goodnessOfFit.
++ Description:
++ \axiomType{AnnaNumericalOptimizationPackage} is a \axiom{package} of 
++ functions for the \axiomType{NumericalOptimizationCategory} 
++ with \axiom{measure} and \axiom{optimize}.
EDF	==> Expression DoubleFloat
LEDF	==> List Expression DoubleFloat
LDF	==> List DoubleFloat
MDF	==> Matrix DoubleFloat
DF	==> DoubleFloat
LOCDF	==> List OrderedCompletion DoubleFloat
OCDF	==> OrderedCompletion DoubleFloat
LOCF	==> List OrderedCompletion Float
OCF	==> OrderedCompletion Float
LEF	==> List Expression Float
EF	==> Expression Float
LF	==> List Float
F	==> Float
LS	==> List Symbol
LST	==> List String
INT	==> Integer
NOA	==> Record(fn:EDF, init:LDF, lb:LOCDF, cf:LEDF, ub:LOCDF)
LSA	==> Record(lfn:LEDF, init:LDF)
IFL	==> List(Record(ifail:Integer,instruction:String))
Entry	==> Record(chapter:String, type:String, domainName: String, 
                     defaultMin:F, measure:F, failList:IFL, explList:LST)
Measure	==> Record(measure:F,name:String, explanations:List String)
Measure2	==> Record(measure:F,explanations:String)
RT	==> RoutinesTable
UNOALSA	==> Union(noa:NOA,lsa:LSA)

AnnaNumericalOptimizationPackage(): with
  measure:NumericalOptimizationProblem -> Measure
    ++ measure(prob) is a top level ANNA function for identifying the most
    ++ appropriate numerical routine from those in the routines table
    ++ provided for solving the numerical optimization problem defined by 
    ++ \axiom{prob} by checking various attributes of the functions and 
    ++ calculating a measure of compatibility of each routine to these 
    ++ attributes.
    ++
    ++ It calls each \axiom{domain} of \axiom{category}
    ++ \axiomType{NumericalOptimizationCategory} in turn to calculate all 
    ++ measures and returns the best i.e. the name of the most 
    ++ appropriate domain and any other relevant information.

  measure:(NumericalOptimizationProblem,RT) -> Measure
    ++ measure(prob,R) is a top level ANNA function for identifying the most
    ++ appropriate numerical routine from those in the routines table
    ++ provided for solving the numerical optimization problem defined by 
    ++ \axiom{prob} by checking various attributes of the functions and 
    ++ calculating a measure of compatibility of each routine to these 
    ++ attributes.
    ++
    ++ It calls each \axiom{domain} listed in \axiom{R} of \axiom{category}
    ++ \axiomType{NumericalOptimizationCategory} in turn to calculate all 
    ++ measures and returns the best i.e. the name of the most 
    ++ appropriate domain and any other relevant information.

  optimize:(NumericalOptimizationProblem,RT) -> Result
    ++ optimize(prob,routines) is a top level ANNA function to 
    ++ minimize a function or a set of functions with any constraints
    ++ as defined within \axiom{prob}.
    ++
    ++ It iterates over the \axiom{domains} listed in \axiom{routines} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.

  optimize:NumericalOptimizationProblem -> Result
    ++ optimize(prob) is a top level ANNA function to 
    ++ minimize a function or a set of functions with any constraints
    ++ as defined within \axiom{prob}.
    ++
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.

  goodnessOfFit:NumericalOptimizationProblem -> Result
    ++ goodnessOfFit(prob) is a top level ANNA function to 
    ++ check to goodness of fit of a least squares model 
    ++ as defined within \axiom{prob}.
    ++
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.
    ++ It then calls the numerical routine \axiomType{E04YCF} to get estimates
    ++ of the variance-covariance matrix of the regression coefficients of 
    ++ the least-squares problem.
    ++ 
    ++ It thus returns both the results of the optimization and the
    ++ variance-covariance calculation.

  optimize:(EF,LF,LOCF,LEF,LOCF) -> Result 
    ++ optimize(f,start,lower,cons,upper) is a top level ANNA function to 
    ++ minimize a function, \axiom{f}, of one or more variables with the 
    ++ given constraints.
    ++
    ++ These constraints may be simple constraints on the variables
    ++ in which case \axiom{cons} would be an empty list and the bounds on
    ++ those variables defined in \axiom{lower} and \axiom{upper}, or a 
    ++ mixture of simple, linear and non-linear constraints, where
    ++ \axiom{cons} contains the linear and non-linear constraints and
    ++ the bounds on these are added to \axiom{upper} and \axiom{lower}.
    ++
    ++ The parameter \axiom{start} is a list of the initial guesses of the
    ++ values of the variables.
    ++ 
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.

  optimize:(EF,LF,LOCF,LOCF) -> Result 
    ++ optimize(f,start,lower,upper) is a top level ANNA function to 
    ++ minimize a function, \axiom{f}, of one or more variables with 
    ++ simple constraints.  The bounds on
    ++ the variables are defined in \axiom{lower} and \axiom{upper}.
    ++
    ++ The parameter \axiom{start} is a list of the initial guesses of the
    ++ values of the variables.
    ++ 
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.

  optimize:(EF,LF) -> Result 
    ++ optimize(f,start) is a top level ANNA function to 
    ++ minimize a function, \axiom{f}, of one or more variables without
    ++ constraints. 
    ++
    ++ The parameter \axiom{start} is a list of the initial guesses of the
    ++ values of the variables.
    ++ 
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.

  optimize:(LEF,LF) -> Result 
    ++ optimize(lf,start) is a top level ANNA function to 
    ++ minimize a set of functions, \axiom{lf}, of one or more variables 
    ++ without constraints i.e. a least-squares problem. 
    ++
    ++ The parameter \axiom{start} is a list of the initial guesses of the
    ++ values of the variables.
    ++ 
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.

  goodnessOfFit:(LEF,LF) -> Result 
    ++ goodnessOfFit(lf,start) is a top level ANNA function to 
    ++ check to goodness of fit of a least squares model i.e. the minimization
    ++ of a set of functions, \axiom{lf}, of one or more variables without 
    ++ constraints.
    ++
    ++ The parameter \axiom{start} is a list of the initial guesses of the
    ++ values of the variables.
    ++ 
    ++ It iterates over the \axiom{domains} of 
    ++ \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.
    ++ It then calls the numerical routine \axiomType{E04YCF} to get estimates
    ++ of the variance-covariance matrix of the regression coefficients of 
    ++ the least-squares problem.
    ++ 
    ++ It thus returns both the results of the optimization and the
    ++ variance-covariance calculation.

    ++ goodnessOfFit(lf,start) is a top level function to iterate over 
    ++ the \axiom{domains} of \axiomType{NumericalOptimizationCategory} 
    ++ to get the name and other relevant information of the best
    ++ \axiom{measure} and then optimize the function on that \axiom{domain}.
    ++ It then checks the goodness of fit of the least squares model.

 == add

  preAnalysis:RT -> RT
  zeroMeasure:Measure -> Result
  optimizeSpecific:(UNOALSA,String) -> Result
  measureSpecific:(String,RT,UNOALSA) -> Measure2
  changeName:(Result,String) -> Result
  recoverAfterFail:(UNOALSA,RT,Measure,INT,Result) -> Record(a:Result,b:Measure)
  constant:UNOALSA -> Union(DF, "failed")
  optimizeConstant:DF -> Result

  import ExpertSystemToolsPackage,e04AgentsPackage,NumericalOptimizationProblem

  constant(args:UNOALSA):Union(DF,"failed") ==
    args case noa =>
      Args := args.noa
      f := Args.fn
      retractIfCan(f)@Union(DoubleFloat,"failed")
    "failed"

  optimizeConstant(c:DF): Result ==
    a := coerce(c)$AnyFunctions1(DF)
    text := coerce("Constant Function")$AnyFunctions1(String)
    construct([[objf@Symbol,a],[method@Symbol,text]])$Result

  preAnalysis(args:UNOALSA,t:RT):RT == 
    r := selectOptimizationRoutines(t)$RT
    args case lsa =>
      selectSumOfSquaresRoutines(r)$RT
    r

  zeroMeasure(m:Measure):Result ==
    a := coerce(0$F)$AnyFunctions1(F)
    text := coerce("Zero Measure")$AnyFunctions1(String)
    r := construct([[objf@Symbol,a],[method@Symbol,text]])$Result
    concat(measure2Result m,r)

  measureSpecific(name:String,R:RT,args:UNOALSA): Measure2 ==
    args case noa =>
      arg:NOA := args.noa
      name = "e04dgfAnnaType" => measure(R,arg)$e04dgfAnnaType
      name = "e04fdfAnnaType" => measure(R,arg)$e04fdfAnnaType
      name = "e04gcfAnnaType" => measure(R,arg)$e04gcfAnnaType
      name = "e04jafAnnaType" => measure(R,arg)$e04jafAnnaType
      name = "e04mbfAnnaType" => measure(R,arg)$e04mbfAnnaType
      name = "e04nafAnnaType" => measure(R,arg)$e04nafAnnaType
      name = "e04ucfAnnaType" => measure(R,arg)$e04ucfAnnaType
      error("measureSpecific","invalid type name: " name)$ErrorFunctions
    args case lsa =>
      arg2:LSA := args.lsa
      name = "e04fdfAnnaType" => measure(R,arg2)$e04fdfAnnaType
      name = "e04gcfAnnaType" => measure(R,arg2)$e04gcfAnnaType
      error("measureSpecific","invalid type name: " name)$ErrorFunctions
    error("measureSpecific","invalid argument type")$ErrorFunctions

  measure(Args:NumericalOptimizationProblem,R:RT):Measure ==
    args:UNOALSA := retract(Args)$NumericalOptimizationProblem
    sofar := 0$F
    best := "none" :: String
    routs := copy R
    routs := preAnalysis(args,routs)
    empty?(routs)$RT => 
      error("measure", "no routines found")$ErrorFunctions
    rout := inspect(routs)$RT
    e := retract(rout.entry)$AnyFunctions1(Entry)
    meth := empty()$(List String)
    for i in 1..# routs repeat
      rout := extract!(routs)$RT
      e := retract(rout.entry)$AnyFunctions1(Entry)
      n := e.domainName
      if e.defaultMin > sofar then
        m := measureSpecific(n,R,args)
        if m.measure > sofar then
          sofar := m.measure
          best := n
        str := [concat(concat([string(rout.key)$Symbol,"measure: ",
                 outputMeasure(m.measure)," - "],
                   m.explanations)$(List String))$String]
      else 
        str := [concat([string(rout.key)$Symbol
                         ," is no better than other routines"])$String]
      meth := append(meth,str)$(List String)
    [sofar,best,meth]

  measure(args:NumericalOptimizationProblem):Measure == measure(args,routines()$RT)

  optimizeSpecific(args:UNOALSA,name:String):Result ==
    args case noa =>
      arg:NOA := args.noa
      name = "e04dgfAnnaType" => numericalOptimization(arg)$e04dgfAnnaType
      name = "e04fdfAnnaType" => numericalOptimization(arg)$e04fdfAnnaType
      name = "e04gcfAnnaType" => numericalOptimization(arg)$e04gcfAnnaType
      name = "e04jafAnnaType" => numericalOptimization(arg)$e04jafAnnaType
      name = "e04mbfAnnaType" => numericalOptimization(arg)$e04mbfAnnaType
      name = "e04nafAnnaType" => numericalOptimization(arg)$e04nafAnnaType
      name = "e04ucfAnnaType" => numericalOptimization(arg)$e04ucfAnnaType
      error("optimizeSpecific","invalid type name: " name)$ErrorFunctions
    args case lsa =>
      arg2:LSA := args.lsa
      name = "e04fdfAnnaType" => numericalOptimization(arg2)$e04fdfAnnaType
      name = "e04gcfAnnaType" => numericalOptimization(arg2)$e04gcfAnnaType
      error("optimizeSpecific","invalid type name: " name)$ErrorFunctions
    error("optimizeSpecific","invalid type name: " name)$ErrorFunctions

  changeName(ans:Result,name:String):Result ==
    st:String := concat([name,"Answer"])$String
    sy:Symbol := coerce(st)$Symbol
    anyAns:Any := coerce(ans)$AnyFunctions1(Result)
    construct([[sy,anyAns]])$Result

  recoverAfterFail(args:UNOALSA,routs:RT,m:Measure,
                     iint:INT,r:Result):Record(a:Result,b:Measure) ==
    while positive?(iint) repeat
      routineName := m.name
      s := recoverAfterFail(routs,routineName(1..6),iint)$RT
      s case "failed" => iint := 0
      (s = "no action")@Boolean => iint := 0
      fl := coerce(s)$AnyFunctions1(String)
      flrec:Record(key:Symbol,entry:Any):=[failure@Symbol,fl]
      m2 := measure(args::NumericalOptimizationProblem,routs)
      zero?(m2.measure) => iint := 0
      r2:Result := optimizeSpecific(args,m2.name)
      m := m2
      insert!(flrec,r2)$Result
      r := concat(r2,changeName(r,routineName))
      iany := search(ifail@Symbol,r2)$Result
      iany case "failed" => iint := 0
      iint := retract(iany)$AnyFunctions1(INT)
    [r,m]

  optimize(Args:NumericalOptimizationProblem,t:RT):Result ==
    args:UNOALSA := retract(Args)$NumericalOptimizationProblem
    routs := copy(t)$RT
    c:Union(DF,"failed") := constant(args)
    c case DF => optimizeConstant(c)
    m := measure(Args,routs)
    zero?(m.measure) => zeroMeasure m
    r := optimizeSpecific(args,n := m.name)
    iany := search(ifail@Symbol,r)$Result
    iint := 0$INT
    if (iany case Any) then
      iint := retract(iany)$AnyFunctions1(INT)
    if positive?(iint) then
      tu:Record(a:Result,b:Measure) := recoverAfterFail(args,routs,m,iint,r)
      r := tu.a
      m := tu.b
    r := concat(measure2Result m,r)
    expl := getExplanations(routs,n(1..6))$RoutinesTable
    expla := coerce(expl)$AnyFunctions1(LST)
    explaa:Record(key:Symbol,entry:Any) := ["explanations"::Symbol,expla]
    r := concat(construct([explaa]),r)
    att:List String := optAttributes(args)
    atta := coerce(att)$AnyFunctions1(List String)
    attr:Record(key:Symbol,entry:Any) := [attributes@Symbol,atta]
    insert!(attr,r)$Result

  optimize(args:NumericalOptimizationProblem):Result == optimize(args,routines()$RT)

  goodnessOfFit(Args:NumericalOptimizationProblem):Result ==
    r := optimize(Args)
    args1:UNOALSA := retract(Args)$NumericalOptimizationProblem
    args1 case noa => error("goodnessOfFit","Not an appropriate problem")
    args:LSA := args1.lsa
    lf := args.lfn
    n:INT := #(variables(args))
    m:INT := # lf
    me := search(method,r)$Result
    me case "failed" => r
    meth := retract(me)$AnyFunctions1(Result)
    na := search(nameOfRoutine,meth)$Result
    na case "failed" => r
    name := retract(na)$AnyFunctions1(String)
    temp:INT := (n*(n-1)) quo 2
    ns:INT :=
      name = "e04fdfAnnaType" => 6*n+(2+n)*m+1+max(1,temp)
      8*n+(n+2)*m+temp+1+max(1,temp)
    nv:INT := ns+n
    ww := search(w,r)$Result
    ww case "failed" => r
    ws:MDF := retract(ww)$AnyFunctions1(MDF)
    fr := search(objf,r)$Result
    fr case "failed" => r
    f := retract(fr)$AnyFunctions1(DF)
    s := subMatrix(ws,1,1,ns,nv-1)$MDF
    v := subMatrix(ws,1,1,nv,nv+n*n-1)$MDF
    r2 := e04ycf(0,m,n,f,s,n,v,-1)$NagOptimisationPackage
    concat(r,r2)

  optimize(f:EF,start:LF,lower:LOCF,cons:LEF,upper:LOCF):Result ==
    args:NOA := [ef2edf(f),[f2df i for i in start],[ocf2ocdf j for j in lower],
                 [ef2edf k for k in cons], [ocf2ocdf l for l in upper]]
    optimize(args::NumericalOptimizationProblem)

  optimize(f:EF,start:LF,lower:LOCF,upper:LOCF):Result ==
    optimize(f,start,lower,empty()$LEF,upper)

  optimize(f:EF,start:LF):Result ==
    optimize(f,start,empty()$LOCF,empty()$LOCF)

  optimize(lf:LEF,start:LF):Result ==
    args:LSA := [[ef2edf i for i in lf],[f2df j for j in start]]
    optimize(args::NumericalOptimizationProblem)

  goodnessOfFit(lf:LEF,start:LF):Result ==
    args:LSA := [[ef2edf i for i in lf],[f2df j for j in start]]
    goodnessOfFit(args::NumericalOptimizationProblem)

@
\section{License}
<<license>>=
--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--All rights reserved.
--
--Redistribution and use in source and binary forms, with or without
--modification, are permitted provided that the following conditions are
--met:
--
--    - Redistributions of source code must retain the above copyright
--      notice, this list of conditions and the following disclaimer.
--
--    - Redistributions in binary form must reproduce the above copyright
--      notice, this list of conditions and the following disclaimer in
--      the documentation and/or other materials provided with the
--      distribution.
--
--    - Neither the name of The Numerical ALgorithms Group Ltd. nor the
--      names of its contributors may be used to endorse or promote products
--      derived from this software without specific prior written permission.
--
--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@
<<*>>=
<<license>>

<<package OPTPACK AnnaNumericalOptimizationPackage>>
@
\eject
\begin{thebibliography}{99}
\bibitem{1} nothing
\end{thebibliography}
\end{document}