' ******************************************************************
' Minimization of a function of several variables along a line
'
' Example taken from "Numerical Recipes":
'
' Func = (X(1)-1)^2 + (X(2)-1)^2 + (X(3)-1)^2
'
' The minimum is F = 0 at (1, 1, 1), i. e. for a step R = 1 from
' X = (0, 0, 0) in the direction DeltaX = (1, 1, 1)
'
' The program tries a series of directions:
'
'          ( Sqrt(2) * Cos [(Pi / 2) * (I / 10)] )
' DeltaX = ( Sqrt(2) * Sin [(Pi / 2) * (I / 10)] )
'          ( 1                                   )
'
' For each pass, the location of the minimum, and the value of the
' function at the minimum, are printed. The minimum is at I = 5
' ******************************************************************

#INCLUDE "fbmath.bi"

CONST Nvar    = 3     ' Number of variables
CONST MaxIter = 1000  ' Max number of iterations
CONST Tol     = 1D-7  ' Required precision (must be > Sqrt(MachEp))

CONST PiDiv20 = 0.1570796326794897#  ' Pi/20

FUNCTION Func(X() AS DOUBLE) AS DOUBLE
' Function to be minimized

  DIM AS DOUBLE A, B, C

  A = X(1) - 1
  B = X(2) - 1
  C = X(3) - 1

  Func = A * A + B * B + C * C

END FUNCTION

SUB PrintResult(I AS INTEGER, X() AS DOUBLE, Fmin AS DOUBLE)

  DIM AS INTEGER J

  PRINT USING "###"; I;

  FOR J = 1 TO Nvar
    PRINT USING "#####.######"; X(J);
  NEXT J

  PRINT USING "    #####.######^^^^"; Fmin
END SUB

DIM AS DOUBLE  X(1 TO Nvar)       ' Starting point
DIM AS DOUBLE  DeltaX(1 TO Nvar)  ' Search direction
DIM AS DOUBLE  R                  ' Initial step
DIM AS DOUBLE  Fmin               ' Function value at minimum
DIM AS INTEGER I                  ' Loop variable
DIM AS DOUBLE  Z                  ' Auxiliary variable

CLS
PRINT "  I      X(1)        X(2)        X(3)               Fmin"
PRINT "------------------------------------------------------------------"

FOR I = 0 TO 10
  X(1) = 0
  X(2) = 0
  X(3) = 0
  Z = I * PiDiv20
  DeltaX(1) = Sqrt2 * COS(Z)
  DeltaX(2) = Sqrt2 * SIN(Z)
  DeltaX(3) = 1
  R = 0.1

  LinMin @Func, X(), DeltaX(), R, MaxIter, Tol, Fmin

  IF MathErr = OptOk THEN
    PrintResult I, X(), Fmin
  ELSE
    PRINT "Non-convergence!"
  END IF
NEXT I

SLEEP

