Version 0.1
00001 /* bclib.c 00002 $Revision: 285 $ $Date: 2006-12-20 09:33:50 -0800 (Wed, 20 Dec 2006) $ 00003 00004 ---------------------------------------------------------------------- 00005 This file is part of BCLS (Bound-Constrained Least Squares). 00006 00007 Copyright (C) 2006 Michael P. Friedlander, Department of Computer 00008 Science, University of British Columbia, Canada. All rights 00009 reserved. E-mail: <mpf@cs.ubc.ca>. 00010 00011 BCLS is free software; you can redistribute it and/or modify it 00012 under the terms of the GNU Lesser General Public License as 00013 published by the Free Software Foundation; either version 2.1 of the 00014 License, or (at your option) any later version. 00015 00016 BCLS is distributed in the hope that it will be useful, but WITHOUT 00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00018 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 00019 Public License for more details. 00020 00021 You should have received a copy of the GNU Lesser General Public 00022 License along with BCLS; if not, write to the Free Software 00023 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 00024 USA 00025 ---------------------------------------------------------------------- 00026 */ 00032 #include <math.h> 00033 #include <stdarg.h> 00034 #include <stdlib.h> 00035 #include <string.h> 00036 #include <stdio.h> 00037 #include <assert.h> 00038 #include <float.h> 00039 #include <setjmp.h> 00040 00041 #include "bclib.h" 00042 00059 void 00060 bcls_project_step( int n, double s[], double step, double x[], 00061 double dx[], double bl[], double bu[] ) 00062 { 00063 int j; 00064 double xpj; 00065 00066 for (j = 0; j < n; j++) { 00067 00068 xpj = x[j] + step*dx[j]; 00069 00070 if ( xpj < bl[j] ) 00071 s[j] = bl[j] - x[j]; 00072 00073 else if ( xpj > bu[j] ) 00074 s[j] = bu[j] - x[j]; 00075 00076 else 00077 s[j] = step * dx[j]; 00078 } 00079 return; 00080 } 00081 00099 int 00100 bcls_examine_bnds( BCLS *ls, const int n, double bl[], double bu[] ) 00101 { 00102 int j, jopen; 00103 double blj, buj; 00104 const double bigL = - ls->BigNum; 00105 const double bigU = ls->BigNum; 00106 const double epsfixed = ls->epsfixed; 00107 00108 // Variable-type counts. No. of variables that 00109 int neql = 0; // are "open" (have an interior) 00110 int nfix = 0; // are fixed 00111 int nneg = 0; // are unbounded below 00112 int npos = 0; // are unbounded above 00113 int nlow = 0; // have a finite lower bound 00114 int nupp = 0; // have a finite upper bound 00115 int nnrm = 0; // have finite lower and upper bounds 00116 int nfre = 0; // are free. 00117 00118 for (j = 0; j < n; j++) { 00119 jopen = 0; 00120 blj = bl[j]; 00121 buj = bu[j]; 00122 00123 if (buj < blj) // Infeasible interval. Exit. 00124 goto infeas; 00125 00126 else if (buj - blj <= epsfixed) // Fixed variable. 00127 nfix++; 00128 00129 else { // Open interval. 00130 neql++; 00131 jopen = 1; 00132 } 00133 00134 if (blj <= bigL && buj == 0 ) nneg++; 00135 if (blj == 0 && buj >= bigU ) npos++; 00136 if (blj > bigL && jopen) nlow++; 00137 if ( buj < bigU && jopen) nupp++; 00138 if (blj > bigL && buj < bigU ) nnrm++; 00139 if (blj <= bigL && buj >= bigU ) nfre++; 00140 } 00141 00142 ls->unconstrained = nfre == n; 00143 00144 PRINT1("\n Bounds:"); 00145 if (ls->unconstrained) { 00146 PRINT1(" problem is unconstrained\n"); 00147 } 00148 else { 00149 PRINT1("\n [-inf,0] [0,inf] Finite bl Finite bu " 00150 " Two bnds Fixed Free\n"); 00151 PRINT1(" %9d %9d %9d %9d %9d %9d %9d\n", 00152 nneg, npos, nlow, nupp, nnrm, nfix, nfre ); 00153 } 00154 00155 return 0; 00156 00157 infeas: 00158 PRINT1(" Infeasible problem: bl[%d] = %10.2e > %10.2e bu[%d]\n", 00159 j, blj, buj, j); 00160 00161 return BCLS_EXIT_INFEA; 00162 } 00163 00174 void 00175 bcls_print_params( BCLS *ls ) 00176 { 00177 PRINT2("\n"); 00178 PRINT2(" Parameters:\n"); 00179 PRINT2(" Rows............. %8d\t", ls->m); 00180 PRINT2(" Columns.......... %8d\n", ls->n); 00181 PRINT2(" Optimality tol... %8.1e\t", ls->optTol); 00182 PRINT2(" Major itn limit.. %8d\n", ls->itnMajLim); 00183 PRINT2(" Damp............. %8.1e\t", ls->damp); 00184 PRINT2(" Minor itn limit.. %8d\n", ls->itnMinLim); 00185 PRINT2(" Linsearch type... %8s\t", 00186 ls->proj_search == BCLS_PROJ_SEARCH_APPROX 00187 ? "approx" : "exact"); 00188 PRINT2(" Linear term...... %8s\n", 00189 ls->c == NULL ? "no" : "yes" ); 00190 PRINT2(" Newton step...... %8s\t", 00191 ls->newton_step == BCLS_NEWTON_STEP_LSQR 00192 ? "lsqr" : "cgls"); 00193 PRINT2(" Gradient step.... %8s\n", 00194 ls->anorm == NULL 00195 ? "unscaled" : "scaled"); 00196 PRINT2(" Preconditoner.... %8s\n", 00197 ls->Usolve == NULL 00198 ? "no" : "yes"); 00199 00200 return; 00201 } 00202 00211 void 00212 bcls_examine_column_scales( BCLS *ls, double anorm[] ) 00213 { 00214 int j; 00215 int minj; // Index of the column with the minimum col scale. 00216 int maxj; // ............................ maximum col scale. 00217 double minnorm; // The value of the minimum col scale. 00218 double maxnorm; // ........................ col scale. 00219 00220 if ( anorm == NULL ) return; 00221 if ( ls->print_level < 2 ) return; 00222 00223 minnorm = 1.0e20; 00224 maxnorm = 0.0; 00225 00226 for (j = 0; j < ls->n; j++) { 00227 if ( minnorm > anorm[j] ) { minnorm = anorm[j]; minj = j; }; 00228 if ( maxnorm < anorm[j] ) { maxnorm = anorm[j]; maxj = j; }; 00229 } 00230 PRINT2( "\n" ); 00231 PRINT2( " Column scales: %6s %7s\n", "column", "norm" ); 00232 PRINT2( " minimum %6d %7.1e\n", minj, minnorm ); 00233 PRINT2( " maximum %6d %7.1e\n", maxj, maxnorm ); 00234 00235 return; 00236 } 00237 00252 void 00253 bcls_print( BCLS *ls, int current_print_level, char *fmt, ...) 00254 { 00255 va_list arg; 00256 char msg[4095+1]; 00257 00258 // Exit immediately if the current print level is too low. 00259 if ( ls->print_level < current_print_level ) 00260 return; 00261 00262 // Format the message. 00263 va_start(arg, fmt); 00264 vsprintf(msg, fmt, arg); 00265 assert(strlen(msg) <= 4095); 00266 va_end(arg); 00267 00268 // Pass the message to the user-defined hook routine. 00269 if (ls->print_hook != NULL && ls->print_hook(ls->print_info, msg) == 0) 00270 return; 00271 00272 // Othwerise, send the message to the standard output */ 00273 fprintf(stdout, "%s", msg); 00274 00275 return; 00276 } 00277 00290 void 00291 bcls_fault( BCLS *ls, char *fmt, ...) 00292 { 00293 va_list arg; 00294 char msg[4095+1]; 00295 00296 // Format the message. 00297 va_start(arg, fmt); 00298 vsprintf(msg, fmt, arg); 00299 assert(strlen(msg) <= 4095); 00300 va_end(arg); 00301 00302 // Pass the message to the user-defined hook routine. 00303 if (ls->fault_hook != NULL && 00304 ls->fault_hook(ls->fault_info, msg) == 0) goto skip; 00305 00306 // Othwerise, send the message to the standard output */ 00307 fprintf(stderr, "%s\n", msg); 00308 00309 skip: 00310 // return to the calling program. 00311 exit(EXIT_FAILURE); 00312 } 00313 00333 int 00334 bcls_primal_inf( int n, double x[], double bl[], double bu[], 00335 double *pInf, int *jpInf ) 00336 { 00337 int j; 00338 double pj = 0; 00339 double blj, buj, xj; 00340 00341 *pInf = 0.0; 00342 *jpInf = -1; 00343 00344 for (j = 0; j < n; j++) { 00345 blj = bl[j]; 00346 buj = bu[j]; 00347 xj = x[j]; 00348 if ( xj > buj ) 00349 pj = xj - buj; 00350 else if ( blj > xj ) 00351 pj = blj - xj; 00352 00353 if (*pInf < pj ) { 00354 *pInf = pj; 00355 *jpInf = j; 00356 } 00357 00358 } 00359 00360 return *pInf > DBL_EPSILON; 00361 } 00362 00382 void 00383 bcls_dual_inf( int n, double x[], double z[], double bl[], double bu[], 00384 double *dInf, int *jInf ) 00385 { 00386 int j; 00387 double dj, blj, buj; 00388 00389 *dInf = 0.0; 00390 *jInf = 0; 00391 00392 for (j = 0; j < n; j++) { 00393 blj = bl[j]; 00394 buj = bu[j]; 00395 if (blj < buj) { 00396 dj = z[j]; 00397 if (dj > 0) 00398 dj = dj * fmin( x[j] - blj, 1.0 ); 00399 else if (dj < 0) 00400 dj = - dj * fmin( buj - x[j], 1.0 ); 00401 00402 if (*dInf < dj) { 00403 *dInf = dj; 00404 *jInf = j; 00405 } 00406 } 00407 } 00408 00409 return; 00410 } 00411 00424 void 00425 bcls_mid( int n, double x[], double bl[], double bu[] ) 00426 { 00427 int j; 00428 00429 for (j = 0; j < n; j++ ) { 00430 if ( x[j] < bl[j] ) x[j] = bl[j]; 00431 else if ( x[j] > bu[j] ) x[j] = bu[j]; 00432 } 00433 return; 00434 } 00435 00452 void 00453 bcls_aprod( BCLS *ls, int mode, int nix, 00454 int ix[], double x[], double y[] ) 00455 { 00456 // Increase the mat-vec counters, unless this is an initialization 00457 // or de-initialization call. 00458 if (mode == BCLS_PROD_INIT || 00459 mode == BCLS_PROD_TERM ) 00460 ;// Relax. 00461 else { 00462 if (nix == 1 ) ls->nAprod1++; 00463 else if (nix < ls->n) ls->nAprodF++; 00464 ls->nAprodT++; 00465 } 00466 00467 // Call the user's routine. 00468 bcls_timer( &(ls->stopwatch[BCLS_TIMER_APROD]), BCLS_TIMER_START ); 00469 00470 int err = ls->Aprod( mode, ls->m, ls->n, nix, ix, x, y, ls->UsrWrk ); 00471 00472 bcls_timer( &(ls->stopwatch[BCLS_TIMER_APROD]), BCLS_TIMER_STOP ); 00473 00474 // Return to top of BCLS's stack if error is signaled. 00475 if (err) 00476 longjmp(ls->jmp_env, BCLS_EXIT_APROD); 00477 return; 00478 } 00479 00496 void 00497 bcls_usolve( BCLS *ls, int mode, int nix, 00498 int ix[], double v[], double w[] ) 00499 { 00500 // Increase the counters only for actual solves. 00501 if (mode == BCLS_PRECON_U || mode == BCLS_PRECON_Ut ) 00502 ls->nUsolve++; 00503 00504 // Call the user's routine. 00505 bcls_timer( &(ls->stopwatch[BCLS_TIMER_USOLVE]), BCLS_TIMER_START ); 00506 00507 int err = ls->Usolve( mode, ls->m, ls->n, nix, ix, v, w, ls->UsrWrk ); 00508 00509 bcls_timer( &(ls->stopwatch[BCLS_TIMER_USOLVE]), BCLS_TIMER_STOP ); 00510 00511 // Return to top of BCLS's stack if error is signaled. 00512 if (err) 00513 longjmp(ls->jmp_env, BCLS_EXIT_USOLVE); 00514 return; 00515 } 00516 00532 int 00533 bcls_callback( BCLS *ls ) 00534 { 00535 if ( ls->CallBack ) 00536 return ls->CallBack( ls, ls->UsrWrk ); 00537 else 00538 return 0; 00539 } 00540 00568 int 00569 bcls_free_vars( BCLS *ls, int n, int ix[], double x[], 00570 double g[], double bl[], double bu[] ) 00571 { 00572 int j; 00573 int nFree = 0; 00574 int low, upp, inc, dec; 00575 const double epsx = ls->epsx; 00576 const double eps = ls->eps; 00577 00578 for (j = 0; j < n; j++) { 00579 00580 low = x[j] - bl[j] < epsx; 00581 upp = bu[j] - x[j] < epsx; 00582 00583 inc = g[j] < eps; 00584 dec = g[j] > eps; 00585 00586 if ( low ) 00587 ; // Relax -- lower bound binding. 00588 else if ( upp ) 00589 ; // Relax -- upper bound binding. 00590 else { 00591 // Var is free to move. 00592 ix[nFree] = j; 00593 nFree++; 00594 } 00595 } 00596 return nFree; 00597 } 00598 00618 int 00619 bcls_heap_del_min( int numElems, double x[], int ix[] ) 00620 { 00621 assert(numElems > 0); 00622 00623 int lastChild = numElems - 1; 00624 00625 // Swap the smallest element with the lastChild. 00626 bcls_dswap( x[0], x[lastChild] ); 00627 bcls_iswap( ix[0], ix[lastChild] ); 00628 00629 // Contract the heap size, thereby discarding the smallest element. 00630 lastChild--; 00631 00632 // Restore the heap property of the contracted heap. 00633 bcls_heap_sift( 0, lastChild, x, ix ); 00634 00635 return numElems - 1; 00636 } 00637 00656 void 00657 bcls_heap_sift( int root, int lastChild, double x[], int ix[] ) 00658 { 00659 int child; 00660 00661 for (; (child = (root * 2) + 1) <= lastChild; root = child) { 00662 00663 if (child < lastChild) 00664 if ( x[child] > x[child+1] ) 00665 child++; 00666 00667 if ( x[child] >= x[root] ) 00668 break; 00669 00670 bcls_iswap( ix[root], ix[child] ); 00671 bcls_dswap( x[root], x[child] ); 00672 } 00673 return; 00674 } 00675 00685 void 00686 bcls_heap_build( int n, double x[], int ix[] ) 00687 { 00688 int i; 00689 00690 for (i = n/2; i >= 0; i--) 00691 bcls_heap_sift( i, n-1, x, ix ); 00692 00693 return; 00694 } 00695 00707 double 00708 bcls_vec_dnorm2( int nix, int ix[], double x[] ) 00709 { 00710 int j, k; 00711 double norm = 0.0; 00712 00713 for (j = 0; j < nix; j++) { 00714 k = ix[j]; 00715 norm += x[k] * x[k]; 00716 } 00717 norm = sqrt(norm); 00718 00719 return norm; 00720 } 00721 00735 void 00736 bcls_dload( const int n, const double alpha, double x[], const int incx ) 00737 { 00738 int i, ix; 00739 00740 if (incx <= 0) return; 00741 00742 ix = 0; 00743 00744 for (i = 0; i < n; i++) { 00745 x[ix] = alpha; 00746 ix += incx; 00747 } 00748 return; 00749 } 00750 00761 void 00762 bcls_gather( const int nix, const int ix[], const double x[], double y[] ) 00763 { 00764 int j, k; 00765 for (j = 0; j < nix; j++) { 00766 k = ix[ j ]; 00767 y[ j ] = x[ k ]; 00768 } 00769 } 00770 00781 void 00782 bcls_scatter( const int nix, const int ix[], const double x[], double y[] ) 00783 { 00784 int j, k; 00785 for (j = 0; j < nix; j++) { 00786 k = ix[ j ]; 00787 y[ k ] = x[ j ]; 00788 } 00789 }
Generated on Sun Mar 4 22:50:03 2007 by Doxygen 1.5.1