⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lgstic4.f90

📁 开发的lm算法,很有用的一种优化算法. 对非线性优化有很大用处
💻 F90
字号:
MODULE data_storage
! The data is stored in this module.
! This is equivalent to a COMMON area in old Fortran.

IMPLICIT NONE
INTEGER, PARAMETER, PRIVATE  :: dp = SELECTED_REAL_KIND(12, 60)

REAL (dp), SAVE  :: x(100), y(100)

END MODULE data_storage



PROGRAM logistic4
! Fit the 4-parameter logistic curve:

!     Y = A + C / [1 + exp{-B(X - D)}]

! by unweighted least squares.

! Latest revision - 25 October 2001

USE Levenberg_Marquardt
USE data_storage
IMPLICIT NONE

INTERFACE
  SUBROUTINE fcn(m, n, x, fvec, fjac, iflag)
    IMPLICIT NONE
    INTEGER, PARAMETER         :: dp = SELECTED_REAL_KIND(12, 60)
    INTEGER, INTENT(IN)        :: m, n
    REAL (dp), INTENT(IN)      :: x(:)
    REAL (dp), INTENT(IN OUT)  :: fvec(:)
    REAL (dp), INTENT(OUT)     :: fjac(:,:)
    INTEGER, INTENT(IN OUT)    :: iflag
  END SUBROUTINE fcn
END INTERFACE

REAL (dp), ALLOCATABLE  :: fvec(:), fjac(:,:)
INTEGER, PARAMETER      :: n = 4                 ! The number of parameters
INTEGER                 :: info, iostatus, ipvt(n), m
REAL (dp)               :: p(n), tol = 1.0E-04_dp

! Read in the data, counting the number of cases.

OPEN(UNIT=8, FILE='lgstic4.dat', STATUS='OLD')
m = 1
DO
  READ(8, *, IOSTAT=iostatus) x(m), y(m)
  IF (iostatus < 0) EXIT
  IF (iostatus > 0) CYCLE    ! Skips cases with errors - e.g. a heading
  m = m + 1
END DO
m = m - 1
ALLOCATE( fvec(m), fjac(m,n) )

! Set starting values for parameters.
! A = p(1), B = p(2), C = p(3), D = p(4)

p(1) = MINVAL( y(1:m) )
p(3) = MAXVAL( y(1:m) ) - p(1)
p(2) = 2.0_dp / ( MAXVAL( x(1:m) ) - MINVAL( x(1:m) ) )
p(4) = 0.5_dp * ( MAXVAL( x(1:m) ) + MINVAL( x(1:m) ) )

CALL lmder1(fcn, m, n, p, fvec, fjac, tol, info, ipvt)

SELECT CASE (info)
  CASE (:-1)
    WRITE(*, *) 'Users FCN returned INFO = ', -info
  CASE (0)
    WRITE(*, *) 'Improper values for input parameters'
  CASE (1:3)
    WRITE(*, *) 'Convergence'
    WRITE(*, '(a, 4g13.5)') ' Final values of A, B, C, D: ', p
  CASE (4)
    WRITE(*, *) 'Residuals orthogonal to the Jacobian'
    WRITE(*, *) 'There may be an error in FCN'
    WRITE(*, '(a, 4g13.5)') ' Final values of A, B, C, D: ', p
  CASE (5)
    WRITE(*, *) 'Too many calls to FCN'
    WRITE(*, *) 'Either slow convergence, or an error in FCN'
    WRITE(*, '(a, 4g13.5)') ' Final values of A, B, C, D: ', p
  CASE (6:7)
    WRITE(*, *) 'TOL was set too small'
    WRITE(*, '(a, 4g13.5)') ' Final values of A, B, C, D: ', p
  CASE DEFAULT
    WRITE(*, *) 'INFO =', info, ' ???'
END SELECT

STOP
END PROGRAM logistic4



SUBROUTINE fcn(m, n, p, fvec, fjac, iflag)
! Calculate either residuals or the Jacobian matrix.
! A = p(1), B = p(2), C = p(3), D = p(4)
! m = no. of cases, n = no. of parameters (4)

USE data_storage
IMPLICIT NONE
INTEGER, PARAMETER         :: dp = SELECTED_REAL_KIND(12, 60)
INTEGER, INTENT(IN)        :: m, n
REAL (dp), INTENT(IN)      :: p(:)
REAL (dp), INTENT(IN OUT)  :: fvec(:)
REAL (dp), INTENT(OUT)     :: fjac(:,:)
INTEGER, INTENT(IN OUT)    :: iflag

! Local variables

REAL (dp), PARAMETER  :: one = 1.0_dp
INTEGER               :: i
REAL (dp)             :: expntl, temp

IF (iflag == 1) THEN
  fvec = y(1:m) - p(1) - p(3)/(one + EXP(-p(2)*(x(1:m) - p(4))))
ELSE IF (iflag == 2) THEN
  fjac(1:m,1) = -one
  DO i = 1, m
    expntl = EXP(-p(2)*(x(i) - p(4)))
    temp = one / (one + expntl)
    fjac(i,2) = - p(3) * temp**2 * (x(i) - p(4)) * expntl
    fjac(i,3) = - temp
    fjac(i,4) =   p(3) * temp**2 * expntl * p(2)
  END DO
END IF

RETURN
END SUBROUTINE fcn

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -