|
| 1 | +lnsrch <- function (xold, fold, g, p, func, dataList, stpmax, |
| 2 | + itermax=20, TOLX=1e-10, dbglev=0) { |
| 3 | + n <- length(xold) |
| 4 | + check <- FALSE |
| 5 | + f2 <- 0 |
| 6 | + alam2 <- 0 |
| 7 | + ALF <- 1e-4 |
| 8 | + psum <- sqrt(sum(p^2)) |
| 9 | + # scale if attempted step is too big |
| 10 | + if (psum > stpmax) { |
| 11 | + p <- p*(stpmax/psum) |
| 12 | + } |
| 13 | + slope <- sum(g*p) |
| 14 | + if (dbglev > 1) print(c(0,0,slope,fold)) |
| 15 | + if (slope >= 0) { |
| 16 | + stop('Initial slope not negative.') |
| 17 | + } |
| 18 | + # compute lambdamin |
| 19 | + test <- 0 |
| 20 | + for (i in 1:n) { |
| 21 | + temp <- abs(p[i])/max(abs(xold[i]),1) |
| 22 | + if (temp > test) { |
| 23 | + test <- temp |
| 24 | + } |
| 25 | + } |
| 26 | + alamin <- TOLX/test |
| 27 | + # always try full Newton step first |
| 28 | + alam <- 1 |
| 29 | + # start of iteration loop |
| 30 | + iter <- 0 |
| 31 | + while (iter <= itermax) { |
| 32 | + iter <- iter + 1 |
| 33 | + x <- xold + alam*p |
| 34 | + # ------------- function evaluation ----------- |
| 35 | + result <- func(x, dataList) |
| 36 | + f <- result$PENSSE |
| 37 | + g <- result$DPENSSE |
| 38 | + if (dbglev > 1) print(c(iter,alam,f)) |
| 39 | + # ----------------------------------------------- |
| 40 | + # convergence on x change. |
| 41 | + if (alam < alamin) { |
| 42 | + x <- xold |
| 43 | + check <- TRUE |
| 44 | + return(list(x=x, check=check)) |
| 45 | + } else { |
| 46 | + # sufficient function decrease |
| 47 | + if (f <= fold + ALF*alam*slope) { |
| 48 | + return(list(x=x, check=check)) |
| 49 | + } |
| 50 | + # backtrack |
| 51 | + if (alam == 1) { |
| 52 | + # first time |
| 53 | + tmplam <- -slope/(2*(f-fold-slope)) |
| 54 | + } else { |
| 55 | + # subsequent backtracks |
| 56 | + rhs1 <- f - fold - alam *slope |
| 57 | + rhs2 <- f2 - fold - alam2*slope |
| 58 | + a <- (rhs1/alam^2 - rhs2/alam2^2)/(alam-alam2) |
| 59 | + b <- (-alam2*rhs1/alam^2 + alam*rhs2/(alam*alam2))/(alam-alam2) |
| 60 | + if (a == 0) { |
| 61 | + tmplam <- -slope/(2*b) |
| 62 | + } else { |
| 63 | + disc <- b^2 - 3*a*slope |
| 64 | + if (disc < 0) { |
| 65 | + tmplam <- 0.5*alam |
| 66 | + } else { |
| 67 | + if (b <= 0) { |
| 68 | + tmplam <- (-b+sqrt(disc))/(3*a) |
| 69 | + } else { |
| 70 | + tmplam <- -slope/(b+sqrt(disc)) |
| 71 | + } |
| 72 | + } |
| 73 | + if (tmplam > 0.5*alam) { |
| 74 | + tmplam <- 0.5*alam |
| 75 | + } |
| 76 | + } |
| 77 | + } |
| 78 | + alam2 <- alam |
| 79 | + f2 <- f |
| 80 | + # lambda > 0.1 lambda1 |
| 81 | + alam <- max(tmplam, 0.1*alam) |
| 82 | + } |
| 83 | + # try again |
| 84 | + } |
| 85 | + |
| 86 | + return(list(x=x, check=check)) |
| 87 | + |
| 88 | +} |
| 89 | + |
0 commit comments