1 subroutine linfs(n, x, y, beta1, beta2, lambda, kount, p, q, r, 2 1 ifault) 3c 4c----------------------------------------------------------------------- 5c 6c Package: SLRPACK 7c 8c Version: October, 1985 9c 10c----------------------------------------------------------------------- 11c 12c PURPOSE 13c ------- 14c 15c This user-callable subroutine solves the simple model, 16c y = beta1 + (beta2)x, under the Chebychev norm criterion. 17c 18c DESCRIPTION 19c ----------- 20c 21c 1. The Y's are observed values of the dependent variable and the 22c X's are the observed values of the independent variables, the 23c predictor variables. 24c 25c 2. The general Chebychev problem is to minimize LAMBDA where 26c 27c LAMBDA = MAX( |Y(i) - BETA1 - X(i)*BETA2| ) over all i 28c 29c such that 30c 31c Y(i)-LAMBDA <= BETA1 + X(i)*BETA2 <= Y(i)+LAMBDA 32c 33c 3. The optimal value of (BETA1, BETA2)' will minimize the 34c maximum deviation and LAMBDA will be the value of this deviation 35c 36c INPUT PARAMETERS 37c ---------------- 38c 39c N Integer scalar (unchanged on output). 40c Number of observations. 41c 42c N must be at least 3. 43c 44c X Real vector dimensioned at least N (unchanged on output). 45c Observed values of the independent variable. 46c 47c Y Real vector dimensioned at least N (unchanged on output). 48c Observed values of the dependent variable. 49c 50c OUTPUT PARAMETERS 51c ----------------- 52c 53c BETA1 Real scalar. 54c The estimated intercept term for the fitted line. 55c 56c BETA2 Real scalar. 57c The estimated slope term for the fitted line. 58c 59c LAMBDA Real scalar. 60c The least maximum absolute deviation, also 61c the objective function value. 62c 63c P Integer scalar. 64c Indicates which row of X is the p-th constraint. 65c 66c Q Integer scalar. 67c Indicates which row of X is the q-th constraint. 68c 69c R Integer scalar. 70c Indicates which row of X is the r-th constraint. 71c 72c KOUNT Integer scalar. 73c The number of iterations. 74c 75c IFAULT Integer scalar. 76c Failure indicator. 77c 78c = 0 normal termination 79c 80c = 1 the data set is too small 81c cannot compute BETA1, BETA2, LAMBDA, P, Q, R 82c 83c = 2 all x values are equal 84c cannot compute BETA1, BETA2, LAMBDA, P, Q, R 85c 86c = 3 the data are collinear, all constraints are feasib 87c cannot compute P, Q, R 88c 89c PRECISION 90c --------- 91c 92c All calculations are done in single precision. 93c 94c LANGUAGE 95c -------- 96c 97c All code is written in standard Fortran 77. 98c 99c OTHER SUBROUTINES 100c ----------------- 101c 102c PORT subroutine R1MACH 103c 104c REFERENCE 105c --------- 106c 107c Sklar, M. and R. Armstrong (1983). "A Linear Programming Algorithm 108c for the Simple Model for Discrete Chebychev Curve Fitting", 109c Computers and Operations Research 10, 237-248. 110c 111c Sklar, M. and R. Armstrong (1984). "An Algorithm for Discrete 112c Chebychev Curve Fitting for the Simple Model Using A Dual 113c Linear Programming Approach", Communications in Statistics: 114c Simulation and Computation, 13(4), 555-569. 115c 116c AUTHORS 117c ------- 118c 119c Michael G. Sklar and Ronald D. Armstrong 120c University of Georgia 121c 122c NBS CONTACT 123c ----------- 124c 125c Sally E. Howe 126c Scientific Computing Division 127c Center for Applied Mathematics 128c National Engineering Labratory 129c 301-921-3395 130c 131c--------------------------------------------------------------------- 132c 133 integer ifault,irow,isave,kount,n 134 integer p,q,r,s 135c 136 real acu,alpha1,alpha2,beta1,beta2,big,d,delhat 137 real delstr,devsgn,div,dsubi,dsubr,dsubs,lambda 138 real ratio,r1,r2,save,signp,signq,signr 139 real signs,s1,s2,sumr,sums,top 140 real x(*), y(*) 141c 142c--------------------- 143c internal variables 144c--------------------- 145c 146c signp, signq, signr, signs Indicators for the p-th, q-th, r-th, 147c and s-th constraints, respectively. 148c 149c sign(k) = 1 If the k-th constraint is at or violates its 150c upper bound. 151c = -1 If it is at or violates its lower bound. 152c 153c dsubi Amount by which the i-th constraint is violated. 154c 155c dsubr Amount by which the r-th constraint is violated. 156c 157c dsubs Amount by which the s-th constraint is violated. 158c 159c delhat The smallest delta necessary to bring constraints into 160c feasibility. 161c 162c delstr The largest tolerable delta allowed before a feasible 163c constraint moves beyond its opposite bound. 164c 165c devsgn The signed amount violated in the s-th constraint. 166c 167c alpha1, alpha2 Y-coordinates of p-th and q-th constraints. 168c 169c acu Machine-dependent constant which is used to test for zero. 170c ACU is set to 100 times the relative machine accuracy. 171c 172c big Machine-dependent constant which is used in determining the 173c minimum ratio. BIG is set to the largest floating point 174c number available. 175c 176 kount=0 177 beta1=0.0 178 beta2=0.0 179 lambda=0.0 180 p=0 181 q=0 182 r=0 183c 184c check problem size 185c 186 if (n .le. 2) then 187 ifault = 1 188 return 189 endif 190 acu = r1mach(4) * 100.0 191 big = r1mach(2) 192 ifault=0 193c 194c get p-th and q-th constraints and 195c check that not all x-values are equal 196c 197 p=1 198 do 110 i=2,n 199 if(abs(x(p)-x(i)).gt.acu)goto 120 200 110 continue 201c 202 ifault=2 203 p = 0 204 return 205c 206 120 q=i 207c 208c step 1 - compute initial (trivial) solution 209c 210 s=0 211 d=1./(x(q)-x(p)) 212 alpha1=y(p) 213 alpha2=y(q) 214 beta1=d*(x(q)*alpha1-x(p)*alpha2) 215 beta2=d*(alpha2-alpha1) 216c 217c step 2 - add a constraint (labeled r-th) to the problem 218c 219 irow=p 220 130 if(irow.eq.n) then 221 ifault=3 222 p=0 223 q=0 224 return 225 endif 226 irow=irow+1 227c 228c check if r-th constraint is feasible 229c (i.e. if p-th, q-th, and r-th constraints are not collinear) 230c 231 dsubr=beta1+x(irow)*beta2-y(irow) 232 if(abs(dsubr).lt.acu)goto 130 233 signr=sign(1.,dsubr) 234 ifault=0 235 r=irow 236c 237c adjust for the r-th constraint 238c 239 r1=d*(x(q)-x(r)) 240 r2=d*(x(r)-x(p)) 241 signp=sign(1.,-signr*r1) 242 signq=sign(1.,-signr*r2) 243 sumr=signr-signp*r1-signq*r2 244 lambda=abs(dsubr/sumr) 245 alpha1=y(p)+signp*lambda 246 alpha2=y(q)+signq*lambda 247 beta1=d*(x(q)*alpha1-x(p)*alpha2) 248 beta2=d*(alpha2-alpha1) 249c 250c step 3 - find a fourth constraint (labeled s-th) which most 251c violates the current solution 252c 253 140 s=0 254 dsubs=acu 255 do 150 i=1,n 256 dsubi=abs(beta1+beta2*x(i)-y(i))-lambda 257 if(dsubi.le.dsubs) go to 150 258 dsubs=dsubi 259 s=i 260 150 continue 261c 262c check for termination - no constraints are violated 263c 264 if(s.eq.0) go to 240 265c 266c compute characteristics of most-violated (s-th) constraint 267c 268 devsgn=beta1+beta2*x(s)-y(s) 269 signs=sign(1.,devsgn) 270 s1=d*(x(q)-x(s)) 271 s2=d*(x(s)-x(p)) 272 sums=-signs+signq*s2 +signp*s1 273c 274c step 4 - determine which constraint will not be binding 275c when the s-th constraint is made feasible (by 276c locating the minimum ratio) 277c 278 160 ratio=big 279c 280c if the signs are not the same, the p-th constraint is not a 281c candidate 282c 283 if(signs*sign(1.,s1).ne.signp)goto 170 284c 285c ignore ratio if denominator is effectively zero 286c 287 if(abs(s1).lt.acu)goto 170 288 ratio=abs(r1/s1) 289c 290c if the signs are not the same, the q-th constraint is not a 291c candidate 292c 293 170 if(signs*sign(1.,s2).ne.signq)goto 180 294c 295c ignore ratio if denominator is effectively zero 296c 297 if(abs(s2).lt.acu)goto 180 298c 299c if minimum is p-th, go to process p-th 300c 301 if(abs(r2/s2).lt.ratio)goto 200 302 go to 210 303c 304c if minimum is q-th, go to switch the p-th and q-th constraints so 305c that the algorithm will always process the p-th constraint 306c 307 180 if(ratio.lt.big)goto 210 308c 309c step 5 - no minimum was located, so process the r-th constraint 310c 311 delhat=abs(dsubs/sums) 312c 313c calculate the largest tolerable delta 314c 315 div=abs(sumr)-2. 316 if(div.lt.acu) go to 190 317 delstr=2.*lambda/div 318 if(delstr.ge.delhat) go to 190 319c 320c step 5a - as the s-th becomes feasible, the r-th becomes 321c infeasible by moving outside a bound, so switch 322c r-th and s-th constraint indicators 323c 324 save=sums 325 sums=-sumr+signr+signr 326 sumr=-save 327 save=signr 328 signr=signs 329 signs=-save 330 dsubs=abs(sums*delhat) -2.*lambda 331 lambda=lambda+delhat 332 alpha1=y(p)+signp*lambda 333 alpha2=y(q)+signq*lambda 334 beta1=d*(x(q)*alpha1-x(p)*alpha2) 335 beta2=d*(alpha2-alpha1) 336 save=r1 337 r1=s1 338 s1=save 339 save=r2 340 r2=s2 341 s2=save 342 isave=r 343 r=s 344 s=isave 345 go to 160 346c 347c step 5b - replace the r-th constraint with the s-th constraint, 348c since the s-th became feasible and the r-th moved 349c interior (between bounds) 350c 351 190 signr=signs 352 r1=s1 353 r2=s2 354 sumr=-sums 355 r=s 356 go to 230 357c 358c step 6 - for efficiency, the algorithm always processes the 359c p-th constraint. if the q-th is to be processed, 360c switch p-th and q-th constraints 361c 362 200 isave=p 363 p=q 364 q=isave 365 save=signp 366 signp=signq 367 signq=save 368 save=alpha1 369 alpha1=alpha2 370 alpha2=save 371 save=r1 372 r1=r2 373 r2=save 374 save=s1 375 s1=s2 376 s2=save 377c 378c step 7 - process the movement of the p-th constraint 379c 380 210 delhat=abs(r1*dsubs/(r1*sums+s1*sumr)) 381 top=-2.*lambda*r1 382 div=r1 +r1 +signp*sumr 383 if(sign(1.,top).ne.sign(1.,div)) go to 220 384 if(abs(div).lt.acu) go to 220 385 delstr=top/div 386c 387c check to see if p-th constraint swings across to its 388c opposite bound 389c 390 if(delstr.ge.delhat) go to 220 391c 392c step 7a - the p-th constraint moves to its opposite bound, 393c and the s-th constraint is still infeasible. 394c adjust for the movement, then go to step 4 to 395c locate the next smallest ratio 396c 397 lambda=lambda+delstr 398 dsubs=dsubs-delstr*abs(sums+s1*sumr/r1) 399 sumr=sumr+2.*signp*r1 400 sums=sums-2.*signp*s1 401 signp=-signp 402 alpha1=y(p)+signp*lambda 403 alpha2=y(q)+signq*lambda 404 go to 160 405c 406c step 7b - the s-th became feasible and the p-th moved interior 407c so replace the p-th constraint with the s-th constraint 408c 409 220 signp=signs 410 r1=r1/s1 411 r2=r2-s2*r1 412 sumr=signr-signp*r1-signq*r2 413 p=s 414 kount=kount+1 415c 416c update lambda, compute the new solution - goto step 3 to 417c locate a new most-violated constraint 418c 419 230 s=0 420 lambda=lambda+delhat 421 alpha1=y(p)+signp*lambda 422 alpha2=y(q)+signq*lambda 423 d=1./(x(q)-x(p)) 424 beta1=d*(x(q)*alpha1-x(p)*alpha2) 425 beta2=d*(alpha2-alpha1) 426 go to 140 427 240 continue 428 return 429 end 430