root / src / Hupdate_MS.f90 @ 4
Historique | Voir | Annoter | Télécharger (2,99 ko)
1 | 4 | pfleura2 | ! Hessian - or its inverse - update |
---|---|---|---|
2 | 4 | pfleura2 | ! We use the Murtagh-Sargent update, also called Symmetric Rank 1 |
3 | 4 | pfleura2 | ! |
4 | 4 | pfleura2 | ! input: |
5 | 4 | pfleura2 | ! - nfree: number of coordinates |
6 | 4 | pfleura2 | ! - ds: GeomOld-Geom (expressed in the optimization coord.) |
7 | 4 | pfleura2 | ! - dgrad: GradOld-Grad (expressed in the optimization coord.) |
8 | 4 | pfleura2 | ! |
9 | 4 | pfleura2 | ! input/output: |
10 | 4 | pfleura2 | ! - Hess: old Hessian in input, replaced by updated Hessian on output |
11 | 4 | pfleura2 | ! (or inverse Hessian) |
12 | 4 | pfleura2 | ! |
13 | 4 | pfleura2 | ! |
14 | 4 | pfleura2 | !!!!!!!!!!!!!!!!!!!!!! |
15 | 4 | pfleura2 | ! The update formula for the Hessian is: |
16 | 4 | pfleura2 | ! (following Fletcher, approximate Hessian is denoted by B) |
17 | 4 | pfleura2 | ! B(k+1)=B+[(y-Bs){(y-Bs)T}]/[{(y-Bs)T}s] |
18 | 4 | pfleura2 | ! |
19 | 4 | pfleura2 | ! it is self dual, ie for the inverse Hessian, denote by H: |
20 | 4 | pfleura2 | ! H(k+1)=H+[(s-Hy){(s-Hy)T}]/[{(s-Hy)T}y] |
21 | 4 | pfleura2 | ! |
22 | 4 | pfleura2 | ! |
23 | 4 | pfleura2 | ! We decompose the computation in two steps: |
24 | 4 | pfleura2 | ! first we compute the update, and then we add it to Hess to get the |
25 | 4 | pfleura2 | ! new Hessian. |
26 | 4 | pfleura2 | ! This allows us to introduce a scaling factor if needed later. |
27 | 4 | pfleura2 | ! |
28 | 4 | pfleura2 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
29 | 1 | equemene | |
30 | 1 | equemene | SUBROUTINE Hupdate_MS(Nfree,ds,dgrad,Hess) |
31 | 1 | equemene | |
32 | 1 | equemene | IMPLICIT NONE |
33 | 1 | equemene | |
34 | 1 | equemene | INTEGER, PARAMETER :: KINT=KIND(1) |
35 | 1 | equemene | INTEGER, PARAMETER :: KREAL=KIND(1.D0) |
36 | 1 | equemene | |
37 | 1 | equemene | INTEGER(KINT), INTENT(IN) :: NFREE |
38 | 1 | equemene | REAL(KREAL), INTENT(INOUT) :: Hess(Nfree,Nfree) |
39 | 1 | equemene | REAL(KREAL), INTENT(IN) :: ds(Nfree) |
40 | 1 | equemene | REAL(KREAL), INTENT(IN) :: dGrad(Nfree) |
41 | 1 | equemene | |
42 | 1 | equemene | |
43 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: HessOld(:,:) , HupMS(:,:) |
44 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: Hup(:,:) |
45 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: HupInt(:) |
46 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: HS(:), Num(:,:) |
47 | 1 | equemene | REAL(KREAL) :: Phi, Num3, Den, Den2,NormDS |
48 | 1 | equemene | CHARACTER(120) :: fmt,fmt2,Line |
49 | 1 | equemene | INTEGER(KINT) :: i,j, idx |
50 | 1 | equemene | |
51 | 4 | pfleura2 | LOGICAL :: debug |
52 | 1 | equemene | |
53 | 4 | pfleura2 | interface |
54 | 4 | pfleura2 | function valid(string) result (isValid) |
55 | 4 | pfleura2 | logical :: isValid |
56 | 4 | pfleura2 | character(*), intent(in) :: string |
57 | 4 | pfleura2 | end function valid |
58 | 4 | pfleura2 | |
59 | 4 | pfleura2 | end interface |
60 | 4 | pfleura2 | |
61 | 4 | pfleura2 | |
62 | 4 | pfleura2 | |
63 | 4 | pfleura2 | |
64 | 1 | equemene | debug=valid("Hupdate").OR.Valid("Hupdate_MS") |
65 | 1 | equemene | |
66 | 1 | equemene | if (debug) Call Header("Entering Hupdate_MS") |
67 | 1 | equemene | |
68 | 4 | pfleura2 | ALLOCATE(HessOld(nfree,nfree), & |
69 | 1 | equemene | Hup(nfree,nfree), & |
70 | 1 | equemene | HupInt(nfree), HS(nfree), & |
71 | 1 | equemene | Num(nfree,nfree)) |
72 | 1 | equemene | |
73 | 1 | equemene | HessOld=Hess |
74 | 1 | equemene | |
75 | 1 | equemene | if (debug) THEN |
76 | 1 | equemene | WRITE(*,*) 'DBG Hupdate HessOld' |
77 | 1 | equemene | Idx=min(12,Nfree) |
78 | 1 | equemene | DO I=1,NFree |
79 | 1 | equemene | WRITE(*,'(12(1X,F8.4))') HessOld(I,1:Idx) |
80 | 1 | equemene | END DO |
81 | 1 | equemene | WRITE(*,*) 'DBG Hupdate ds' |
82 | 1 | equemene | WRITE(*,'(12(1X,F8.4))') ds(1:Idx) |
83 | 1 | equemene | WRITE(*,*) 'DBG Hupdate dGrad' |
84 | 1 | equemene | WRITE(*,'(12(1X,F8.4))') dGrad(1:Idx) |
85 | 1 | equemene | END IF |
86 | 1 | equemene | |
87 | 1 | equemene | NormDS=sqrt(DOT_PRODUCT(DS,DS)) |
88 | 1 | equemene | if (NormDS>=1e-6) THEN |
89 | 1 | equemene | |
90 | 1 | equemene | HS=0 |
91 | 1 | equemene | DO I=1,nfree |
92 | 1 | equemene | DO J=1,nfree |
93 | 1 | equemene | HS(I)=HS(I)+HessOld(i,j)*Ds(j) |
94 | 1 | equemene | END DO |
95 | 1 | equemene | END DO |
96 | 4 | pfleura2 | |
97 | 4 | pfleura2 | if (debug) WRITE(*,*) "HS:",HS |
98 | 1 | equemene | HupInt=DGrad-HS |
99 | 1 | equemene | |
100 | 1 | equemene | ! WE calculate the MS update |
101 | 1 | equemene | Num=0. |
102 | 1 | equemene | Den=0. |
103 | 1 | equemene | DO I=1,nfree |
104 | 1 | equemene | DO J=1,nfree |
105 | 1 | equemene | Num(I,J)=HUpInt(i)*HupInt(j) |
106 | 1 | equemene | END DO |
107 | 1 | equemene | Den=Den+Hupint(i)*Ds(i) |
108 | 1 | equemene | END DO |
109 | 4 | pfleura2 | if (debug) WRITE(*,*) "Den:",Den,1./Den |
110 | 1 | equemene | |
111 | 4 | pfleura2 | Hup=Num/Den |
112 | 1 | equemene | |
113 | 4 | pfleura2 | Hess=HessOld+Hup |
114 | 1 | equemene | ELSE |
115 | 1 | equemene | Hess=HessOld |
116 | 1 | equemene | END IF |
117 | 1 | equemene | ! WRITE(*,*) 'New hess' |
118 | 1 | equemene | ! DO I=1,nfree |
119 | 1 | equemene | ! WRITE(*,fmt) Hess(i,:) |
120 | 1 | equemene | ! END DO |
121 | 1 | equemene | |
122 | 4 | pfleura2 | DEALLOCATE(HessOld,Hup, HupInt, HS, Num ) |
123 | 1 | equemene | |
124 | 1 | equemene | if (debug) Call Header("Hupdate_MS Over") |
125 | 1 | equemene | |
126 | 1 | equemene | END SUBROUTINE Hupdate_MS |