local bool too_close(double x1, double x2) { if((x2 == 0.0) && (wn_abs(x1) < sqrt_tolerance)) { return(TRUE); } else if((x1 == 0.0) && (wn_abs(x2) < sqrt_tolerance)) { return(TRUE); } else if( (wn_sign(x1) == wn_sign(x2)) && (fract_diff(x1, x2) < sqrt_tolerance) ) { return(TRUE); } else if(wn_abs(x1 - x2) < sqrt_tolerance) { return(TRUE); } return(FALSE); }
local double fract_diff(double n1,double n2) { n1 = wn_abs(n1); n2 = wn_abs(n2); if(n1 > n2) { return(1.0-n2/n1); } else if(n2 > n1) { return(1.0-n1/n2); } else if(n1 == n2) { return(0.0); } else { return(1.0); } }
local void lo_verify_this_handle_tree ( wn_mbhandle handle_tree, wn_mbhandle parent, int (*pcompare_keys_func)(ptr key1,ptr key2) ) { int left_count,right_count,left_level,right_level; wn_assert(handle_tree->parent == parent); wn_assert(handle_tree->level >= 1); wn_assert(handle_tree->count >= 1); left_count = lo_handle_tree_count(handle_tree->left_child); right_count = lo_handle_tree_count(handle_tree->right_child); left_level = lo_handle_tree_level(handle_tree->left_child); right_level = lo_handle_tree_level(handle_tree->right_child); wn_assert(handle_tree->count == left_count+right_count+1); wn_assert(handle_tree->level == wn_max(left_level,right_level)+1); wn_assert(wn_abs(left_level-right_level) <= 2); if(handle_tree->left_child != NULL) { wn_assert( (*pcompare_keys_func)(handle_tree->left_child->key, handle_tree->key) <= 0 ); wn_assert(handle_tree->left_child->parent == handle_tree); } if(handle_tree->right_child != NULL) { wn_assert( (*pcompare_keys_func)(handle_tree->key, handle_tree->right_child->key) <= 0 ); wn_assert(handle_tree->right_child->parent == handle_tree); } } /* lo_verify_this_handle_tree */
local void line_minimize ( double vect[], double direction[], double *pval_min, double *psave_x0, double *psave_a, double (*pfunction)(double vect[]) ) { double ax,bx,cx,x0,fa,fb,fc,fx0; double a,b; double old_x0,old_a; int code; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) { printf("start line minimize.\n"); } last_line_function_x_valid = FALSE; wn_copy_vect(buffer_vect,vect,num_vars); save_vect = vect; save_direction = direction; save_pfunction = pfunction; old_x0 = *psave_x0; old_a = *psave_a; bx = 0.0; fb = *pval_min; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("First point at %lg, function value = %lg\n", bx, fb); } if(old_x0 == 0.0) { old_x0 = 1.0; } ax = old_x0*wn_random_double_between(0.9,1.1); if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Second point at %lg (old_x0 = %lg)\n", ax, old_x0); } fa = line_function(ax); if(!(old_a > 0.0)) { goto simple_parabola_fit; } /* the curvature along a search direction is constant for a quadratic function, therefore, try to use the curvature from the last search */ fit_parabola_2pa(&code,&x0,&b,old_a,ax,fa,bx,fb); if( (code != WN_SUCCESS) || (!(wn_abs(x0)<MAX_EXPAND*wn_abs(old_x0)) && (*psave_x0 != 0.0)) || too_close(x0, ax) || too_close(x0, bx) || !is_valid_number(x0) || !is_valid_number(ax) || !is_valid_number(bx) ) { goto simple_parabola_fit; } cx = x0; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Third point at %lg\n", cx); } fc = line_function(cx); wn_fit_parabola_3p(&code,&a,&x0,&b,ax,fa,bx,fb,cx,fc); if((code != WN_SUCCESS)||(!(a > 0.0))|| (!(wn_abs(x0)<MAX_EXPAND*wn_abs(old_x0))&&(*psave_x0 != 0.0))) { goto full_linesearch; } if(!(b < fb)) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Doing slow line search (parabola fit returned suspect min value).\n"); } goto full_linesearch; } if((!(fc < fb))||(!(fc < fa))) { /* evaluate one more point */ goto evaluate_x0; } /* is it economical to evaluate one more point? */ if((fb-b) <= 1.5*(fb-fc)) { /* do not evaluate one more point */ wn_swap(fb,fc,double); wn_swap(bx,cx,double); goto finish; } else { /* evaluate one more point */ goto evaluate_x0; } simple_parabola_fit: if(fa < fb) { cx = 2.0*ax*wn_random_double_between(0.8,1.2); } else { cx = -1.0*ax*wn_random_double_between(0.8,1.2); } fc = line_function(cx); wn_fit_parabola_3p(&code,&a,&x0,&b,ax,fa,bx,fb,cx,fc); if((code != WN_SUCCESS)||(!(a > 0.0))|| (!(wn_abs(x0)<MAX_EXPAND*wn_abs(old_x0))&&(*psave_x0 != 0.0))) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Parabola fit failed. Switching to slow line search mode.\n"); } goto full_linesearch; } evaluate_x0: fx0 = line_function(x0); if(!(fx0 <= fb)) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Doing a slow line search because f(x0) is too large (x0 = %lg).\n", x0); } goto full_linesearch; } fb = fx0; bx = x0; if(!(fa <= fc)) { wn_swap(fa,fc,double); wn_swap(ax,cx,double); } if(!(fb <= fa)) { wn_swap(fb,fa,double); wn_swap(bx,ax,double); } goto finish; full_linesearch: ; /* printf("now.\n"); */ do { if(ax == bx) { if(wn_random_bit()) { ax += wn_random_double_between(-1.0,1.0); fa = line_function(ax); } else { bx += wn_random_double_between(-1.0,1.0); fb = line_function(bx); } } if(ax == cx) { if(wn_random_bit()) { ax += wn_random_double_between(-1.0,1.0); fa = line_function(ax); } else { cx += wn_random_double_between(-1.0,1.0); fc = line_function(cx); } } if(bx == cx) { if(wn_random_bit()) { bx += wn_random_double_between(-1.0,1.0); fb = line_function(bx); } else { cx += wn_random_double_between(-1.0,1.0); fc = line_function(cx); } } } while((ax == bx)||(ax == cx)||(bx == cx)); wn_minimize_1d_raw(&code,&fa,&fb,&fc,&ax,&bx,&cx,fb,&line_function,1,20); /* printf("l = %lf\n",bx); */ finish: ; /* if(show_linesearch) { printf("ax=%lg,bx=%lg,cx=%lg,old_x0=%lg\n",ax,bx,cx,old_x0); } */ wn_copy_vect(vect,buffer_vect,num_vars); /* compute *psave_x0 */ if(wn_abs(bx) < MIN_CONTRACT*wn_abs(old_x0)) { if(bx < 0.0) { *psave_x0 = -MIN_CONTRACT*wn_abs(old_x0); } else { *psave_x0 = MIN_CONTRACT*wn_abs(old_x0); } } else { *psave_x0 = bx; } /* compute *psave_a */ wn_fit_parabola_3p(&code,&a,&x0,&b,ax,fa,bx,fb,cx,fc); if((code != WN_SUCCESS)||(!(a > 0.0))) { *psave_a = 0.0; } else { *psave_a = a; } if(*pval_min == fb) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) { printf("finish line minimize.\n"); fflush(stdout); } return; /* do not move if no improvement */ } wn_add_scaled_vect(vect,direction,bx,num_vars); *pval_min = fb; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) { printf("finish line minimize.\n"); fflush(stdout); } }
local void line_minimize ( wn_cdn_context_type c, wn_cdn_srchdir_type search_direction, double *px_width_sum ) { double *search_direction_vect; double poly[3],poly_total_noise[3]; double xopt,fopt,dfopt,fopt_noise,dfopt_noise; double x_width; double x0,x1,x2,f0,f1,f2,df0,df1,df2, f0_noise,f1_noise,f2_noise,df0_noise,df1_noise,df2_noise; int code; double a; double diff_noise; printf("line minimize: coord = %d\n", search_direction->coord); printf(" x_width = %lg\n",search_direction->x_width); x_width = search_direction->x_width; find_taylor_poly(c,poly,poly_total_noise,search_direction,0.0); if(poly_total_noise[1] == 0.0) { search_direction->ratio_df1_noise = WN_FHUGE; } else { search_direction->ratio_df1_noise = wn_abs(poly[1])/poly_total_noise[1]; } printf(" x_width = %lg\n",search_direction->x_width); printf("poly=\n"); wn_print_vect(poly,3); printf("poly_total_noise=\n"); wn_print_vect(poly_total_noise,3); /* try to find min using slope and curvature - this should work most of the time */ if(poly[2] >= 2.0*poly_total_noise[2]) { xopt = -0.5*poly[1]/poly[2]; printf(" xopt = %lg\n",xopt); if((-x_width < xopt)&&(xopt < x_width)) { printf("slope-curvature method successful!!!!!!\n"); fopt = wn_eval_poly(xopt,poly,3); goto finish; } else { printf("slope-curvature method failed because xopt too far out\n"); x0 = xopt; } } else { printf("slope-curvature method failed because non-positive curvature\n"); x0 = search_direction->x0; if(x0 == 0.0) { x0 = search_direction->x_width; } if(poly[1] < 0.0) { x0 = wn_abs(x0); } else if(poly[1] > 0.0) { x0 = -wn_abs(x0); } } if((-search_direction->x_width < x0)&&(x0 < search_direction->x_width)) { if(x0 < 0.0) { x0 = -search_direction->x_width; } else { wn_assert(x0 >= 0.0); x0 = search_direction->x_width; } } /* try secant method using slopes */ secant: ; printf("trying secant method....\n"); x1 = 0.0; f1 = poly[0]; df1 = poly[1]; f1_noise = poly_total_noise[0]; df1_noise = poly_total_noise[1]; find_taylor_poly(c,poly,poly_total_noise,search_direction,x0); f0 = poly[0]; df0 = poly[1]; f0_noise = poly_total_noise[0]; df0_noise = poly_total_noise[1]; printf("x0 = %lg\n",x0); printf("poly=\n"); wn_print_vect(poly,3); printf("poly_total_noise=\n"); wn_print_vect(poly_total_noise,3); wn_fit_parabola_2d(&code,&a,&xopt,x0,df0,x1,df1); printf("code = %d,a = %lg, xopt = %lg\n",code,a,xopt); if((code != WN_SUCCESS)||(!(a > 0.0))|| (!(wn_abs(xopt)<MAX_EXPAND*wn_abs(x0)))) { printf("secant method failed because parabola fit failed.\n"); goto full_linesearch; } find_taylor_poly(c,poly,poly_total_noise,search_direction,xopt); fopt = poly[0]; dfopt = poly[1]; fopt_noise = poly_total_noise[0]; dfopt_noise = poly_total_noise[1]; printf("xopt = %lg\n",xopt); printf("poly=\n"); wn_print_vect(poly,3); printf("poly_total_noise=\n"); wn_print_vect(poly_total_noise,3); diff_noise = sqrt(wn_square(f1_noise)+wn_square(fopt_noise)); if((fopt-f1) > 2.0*diff_noise) { printf("secant method failed because f increased too much\n"); goto full_linesearch; } if(!(wn_abs(dfopt) <= wn_abs(df1))) { printf("secant method failed because df increased\n"); goto full_linesearch; } printf("secant method successful!!!!!!\n"); goto finish; /* full linesearch: search out, or in by 2x steps*/ full_linesearch: ; if(wn_abs(df1) <= 2.0*df1_noise) { xopt = x1; fopt = f1; dfopt = df1; printf("full linesearch failed because slope indistinguishable from 0\n"); goto finish; } if(df1 < 0.0) { wn_assert(x0 > 0.0); } else if(df1 > 0.0) { wn_assert(x0 < 0.0); } else { wn_assert_notreached(); } printf("df1 = %lg,df0 = %lg\n",df1,df0); if(wn_sign(df1) == wn_sign(df0)) { printf("searching outward....\n"); /* search outward until slopes differ */ while(wn_sign(df1) == wn_sign(df0)) { xopt = x0; fopt = f0; dfopt = df0; x0 *= 2.0; find_taylor_poly(c,poly,poly_total_noise,search_direction,x0); f0 = poly[0]; df0 = poly[1]; printf("xopt=%lg,fopt=%lg,dfopt=%lg,x0=%lg,f0=%lg,df0=%lg,x1=%lg,f1=%lg,df1=%lg\n", xopt,fopt,dfopt,x0,f0,df0,x1,f1,df1); } } else if(wn_sign(df1) == -wn_sign(df0)) { xopt = x0; fopt = f0; dfopt = df0; printf("searching inward....\n"); while(wn_sign(dfopt) == -wn_sign(df1)) { xopt *= 0.5; find_taylor_poly(c,poly,poly_total_noise,search_direction,xopt); fopt = poly[0]; dfopt = poly[1]; printf("xopt=%lg,fopt=%lg,dfopt=%lg,x1=%lg,f1=%lg,df1=%lg\n", xopt,fopt,dfopt,x1,f1,df1); } } else { wn_assert_notreached(); } finish: ; compute_search_direction_vect(c,&search_direction_vect,search_direction); wn_cdn_compute_func_call_vect(c,search_direction_vect,xopt); wn_copy_vect(c->current_vect,c->func_call_vect,c->num_vars); retire_search_direction_vect(c,&search_direction_vect,search_direction); if(xopt != 0.0) { (*px_width_sum) += wn_abs(xopt)/search_direction->x_width; } c->ob = fopt; printf("finish: xopt = %lg, fopt = %lg\n",xopt,fopt); }
local void fit_experiments_to_poly2 ( double poly[3], double poly_total_noise[3], double poly_random_noise[3], double poly_systematic_noise[3], double *precommend_widen, double x_vect[], double f_vect[], int n ) { int i,j,code; double **m,**mlsinv,**m3lsinv; double poly4[4],poly4_random_noise[4]; double total4_noise2; double poly3_2; double *x3_vect; wn_assert(n > 4); wn_gpmake("no_free"); wn_make_mat(&m,n,4); for(i=0;i<n;++i) for(j=0;j<4;++j) { m[i][j] = pow(x_vect[i],(double)j); } wn_make_vect(&x3_vect,n); for(i=0;i<n;++i) { x3_vect[i] = m[i][3]; } wn_make_mat(&m3lsinv,3,n); ls_invert_mat(&code,m3lsinv,m,n,3); wn_assert(code == WN_SUCCESS); wn_make_mat(&mlsinv,4,n); ls_invert_mat(&code,mlsinv,m,n,4); wn_assert(code == WN_SUCCESS); wn_mult_mat_by_vect(poly,m3lsinv,f_vect, 3,n); /* printf("poly = \n"); wn_print_vect(poly,3); */ wn_mult_mat_by_vect(poly4,mlsinv,f_vect, 4,n); compute_noise2(&total4_noise2,m,poly4,f_vect,n,4); /* printf("total4_noise2 = %lg\n",total4_noise2); printf("poly4 = \n"); wn_print_vect(poly4,4); */ for(i=0;i<4;++i) { poly4_random_noise[i] = sqrt(total4_noise2*wn_norm2_vect(mlsinv[i],n)); } for(i=0;i<3;++i) { /* use total4_noise2 because it is the most accurate estimate of function noise that we have */ poly_random_noise[i] = sqrt(total4_noise2*wn_norm2_vect(m3lsinv[i],n)); } poly3_2 = wn_square(poly4[3]) - wn_square(poly4_random_noise[3]); /* printf("poly3_2(%lg) = wn_square(poly4[3])(%lg) - wn_square(poly4_random_noise[3])(%lg)\n", poly3_2,wn_square(poly4[3]),wn_square(poly4_random_noise[3])); */ if(poly3_2 < 0.0) { poly3_2 = 0.0; } wn_mult_mat_by_vect(poly_systematic_noise,m3lsinv,x3_vect, 3,n); for(i=0;i<3;++i) { poly_systematic_noise[i] = sqrt(poly3_2)*wn_abs(poly_systematic_noise[i]); } for(i=0;i<3;++i) { poly_total_noise[i] = sqrt(wn_square(poly_random_noise[i])+ wn_square(poly_systematic_noise[i])); } if(poly_systematic_noise[1] == 0.0) { *precommend_widen = WN_FHUGE; } else { *precommend_widen = pow(0.5*wn_square(poly_random_noise[1])/ wn_square(poly_systematic_noise[1]),1.0/6.0); } wn_gpfree(); }
EXTERN void wn_conj_gradient_method ( int *pcode, double *pval_min, double vect[], int len, double (*pfunction)(double vect[]), void (*pgradient)(double grad[],double vect[]), int max_iterations ) { int iteration,no_move_count; int stable_satisfy_count; double norm2_g,norm2_last_g,g_dot_last_g,val,last_val,beta, jump_len,last_jump_len,alpha; double *g,*last_g,*direction; bool function_free_method,last_was_function_free_method; bool first_parabolic_fit_succeeded; double computed_g_dot_dlast; old_group = wn_curgp(); wn_gpmake("no_free"); wn_force_optimize_stop_flag = FALSE; wn_make_vect(&buffer_vect,len); wn_make_vect(&g,len); wn_make_vect(&last_g,len); wn_make_vect(&direction,len); function_free_method = FALSE; stable_satisfy_count = 0; last_was_function_free_method = FALSE; jump_len = 1.0; no_move_count = 0; beta = 0.0; wn_gppush(old_group); val = (*pfunction)(vect); (*pgradient)(g,vect); wn_copy_vect(direction,g,len); norm2_g = wn_norm2_vect(g,len); for(iteration=0;;++iteration) { last_dy1 = dy1; last_jump_len = jump_len; wn_swap(last_g,g,double *); /* move g to last g */ norm2_last_g = norm2_g; if(function_free_method) { double x2; double g0_dot_d0,g1s_dot_d0,dot_diff; dy1 = wn_dot_vects(direction,last_g,len); last_jump_len = -wn_sign(dy1)*wn_abs(last_jump_len); x2 = last_jump_len; /* printf("last_jump_len = %lg\n",last_jump_len); */ wn_add_vect_and_scaled_vect(buffer_vect,vect,direction,last_jump_len,len); (*pgradient)(g,buffer_vect); /* g0_dot_d0 = wn_dot_vects(last_g,direction,len); */ g0_dot_d0 = dy1; g1s_dot_d0 = wn_dot_vects(g,direction,len); dot_diff = g0_dot_d0-g1s_dot_d0; if(!(dot_diff > 0.0)) /* not upward facing parabola */ { stable_satisfy_count = 0; goto function_based_method; } alpha = g0_dot_d0/dot_diff; /* printf("alpha = %lg\n",alpha); */ if(!(((1.0-10000.0) < alpha)&&(alpha < (1.0+10000.0)))) { stable_satisfy_count = 0; goto function_based_method; } jump_len = alpha*last_jump_len; /* g[j] = alpha*g[j] + (1.0-alpha)*last_g[j]; */ wn_scale_vect(g,alpha,len); wn_add_scaled_vect(g,last_g,1.0-alpha,len); g_dot_last_g = wn_dot_vects(g,last_g,len); if(beta != 0.0) { computed_g_dot_dlast = -g_dot_last_g/beta; /* printf("computed_g_dot_dlast=%lg,last_dy1=%lg\n", computed_g_dot_dlast,last_dy1); */ if(!(wn_abs(computed_g_dot_dlast) < 0.4*wn_abs(last_dy1))) { stable_satisfy_count = 0; goto function_based_method; } } wn_add_scaled_vect(vect,direction,alpha*last_jump_len,len); if( wn_force_optimize_stop_flag || ((max_iterations < WN_IHUGE)&&(iteration >= max_iterations)) ) { wn_force_optimize_stop_flag = FALSE; wn_gppop(); wn_gpfree(); val = (*pfunction)(vect); *pval_min = val; *pcode = WN_SUBOPTIMAL; return; } } else /* function based method */ { function_based_method: if(last_was_function_free_method) { /* set so that next iteration will succeed */ val = (*pfunction)(vect); } function_free_method = FALSE; if(norm2_last_g == 0.0) /* unlikely */ { wn_gppop(); wn_gpfree(); *pval_min = val; *pcode = WN_SUCCESS; return; } last_val = val; line_minimize(pcode,&first_parabolic_fit_succeeded,&val,&jump_len, vect, direction,last_val,last_g,last_jump_len,len,pfunction); if(*pcode != WN_SUCCESS) { wn_gppop(); wn_gpfree(); *pval_min = val; return; } if( wn_force_optimize_stop_flag || ((max_iterations < WN_IHUGE)&&(iteration >= max_iterations)) ) { wn_force_optimize_stop_flag = FALSE; wn_gppop(); wn_gpfree(); *pval_min = val; *pcode = WN_SUBOPTIMAL; return; } wn_assert(val <= last_val); if(val == last_val) { if(no_move_count >= 2) { wn_gppop(); wn_gpfree(); *pval_min = val; *pcode = WN_SUCCESS; return; } else { ++no_move_count; jump_len = last_jump_len; } } else { no_move_count = 0; } (*pgradient)(g,vect); g_dot_last_g = wn_dot_vects(g,last_g,len); if((!first_parabolic_fit_succeeded)||(last_jump_len == 0.0)) { stable_satisfy_count = 0; goto no_function_method_test_fail; } alpha = jump_len/last_jump_len; if(!(((1.0-3000.0) < alpha)&&(alpha < (1.0+3000.0)))) { stable_satisfy_count = 0; goto no_function_method_test_fail; } if(beta != 0.0) { computed_g_dot_dlast = -g_dot_last_g/beta; /* printf("computed_g_dot_dlast=%lg,last_dy1=%lg\n", computed_g_dot_dlast,last_dy1); */ if(!(wn_abs(computed_g_dot_dlast) < 0.2*wn_abs(last_dy1))) { stable_satisfy_count = 0; goto no_function_method_test_fail; } } ++stable_satisfy_count; if(stable_satisfy_count > 3) { function_free_method = TRUE; } no_function_method_test_fail: ; } norm2_g = wn_norm2_vect(g,len); /* g_dot_last_g = wn_dot_vects(g,last_g,len); */ beta = (norm2_g - g_dot_last_g)/norm2_last_g; wn_add_vect_and_scaled_vect(direction,g,direction,beta,len); /* printf("norm(g) = %lg\n",wn_norm_vect(g,len)); printf("ob = %lg,beta = %lg,numerator=%lg,denom=%lg,norm2(direction)=%lg\n", val,beta,numerator,norm2_last_g,wn_norm2(direction)); printf("iteration = %d,ob = %lg\n",iteration,val); */ last_was_function_free_method = function_free_method; } }
local void line_minimize ( int *pcode, bool *pfirst_parabolic_fit_succeeded, double *pval, double *pjump_len, double vect[], double direction[], double last_val, double last_g[], double last_jump_len, int len, double (*pfunction)(double vect[]) ) { double a,x0,y0,b,x1,y1,x2,y2; int code; *pcode = WN_SUCCESS; x1 = 0.0; y1 = last_val; dy1 = wn_dot_vects(direction,last_g,len); if(last_jump_len == 0.0) { last_jump_len = 1.0; } last_jump_len = -wn_sign(dy1)*wn_abs(last_jump_len); x2 = last_jump_len; eval_function(&y2,vect,direction,x2,len,pfunction); wn_fit_parabola_2pd(&code,&a,&x0,&b,x1,y1,dy1,x2,y2); /* look for excuses to say that parabolic fit is no good */ if(code != WN_SUCCESS) { /* printf("parabola fit failed - probably a line.\n"); */ x0 = x2+GOLDEN_RATIO*x2; /* project outward */ eval_function(&y0,vect,direction,x0,len,pfunction); goto parabolic_fit_failed; } if(!(a > 0)) { /* printf("downward facing parabola.\n"); */ x0 = x2+GOLDEN_RATIO*x2; /* project outward */ eval_function(&y0,vect,direction,x0,len,pfunction); goto parabolic_fit_failed; } if(!(wn_abs(x0) < 10000.0*wn_abs(x2))) { /* printf("x0 too far out.\n"); */ x0 = 10000.0*x2; /* project outward */ eval_function(&y0,vect,direction,x0,len,pfunction); goto parabolic_fit_failed; } if(!(wn_abs(x0) > (1.0/10000.0)*wn_abs(x2))) { /* printf("x0 too far in.\n"); */ x0 = (1.0/10000.0)*x2; /* project inward */ eval_function(&y0,vect,direction,x0,len,pfunction); goto parabolic_fit_failed; } if(!(b < y1)) /* no improvement expected,weird form for Nan problems */ { /* printf("no improvement expected.\n"); */ x0 = GOLDEN_SECTION*x2; eval_function(&y0,vect,direction,x0,len,pfunction); goto parabolic_fit_failed; } eval_function(&y0,vect,direction,x0,len,pfunction); if(parabola_fit_improvement_wrong(y1,y0,b,0.25)) { /* printf("poor parabola fit detected.\n"); */ goto parabolic_fit_failed; } /* parabolic fit succeeded */ if(y0 > y1) { x0 = x1; y0 = y1; } *pval = y0; *pjump_len = x0; wn_copy_vect(vect,buffer_vect,len); *pfirst_parabolic_fit_succeeded = TRUE; /* *pfirst_parabolic_fit_succeeded = !parabola_fit_improvement_wrong(y1,y0,b,0.25); */ return; parabolic_fit_failed: *pfirst_parabolic_fit_succeeded = FALSE; save_vect = vect; save_direction = direction; save_len = len; save_pfunction = pfunction; wn_minimize_1d_raw(pcode,&y1,&y0,&y2,&x1,&x0,&x2,y1,(simple_eval_function), 3,20); if(!((*pcode == WN_SUCCESS)||(*pcode == WN_SUBOPTIMAL))) { return; } *pcode = WN_SUCCESS; if(y0 <= last_val) { *pval = y0; *pjump_len = x0; wn_add_scaled_vect(vect,direction,x0,len); } else { *pval = last_val; *pjump_len = 0.0; } return; }
void main(void) { int code,i; double val_min,val; double *vect; wn_gpmake("no_free"); wn_make_vect(&p,SIZE); wn_make_vect(&vect,SIZE); for(i=0;i<SIZE;++i) { val = wn_normal_distribution(); p[i] = wn_abs(val); /* p[i] = 1.0; */ } for(i=0;i<SIZE-1;++i) { vect[i] = 1.0/SIZE*(1.0+0.01*wn_normal_distribution()); /* vect[i] = 1.0/SIZE; */ } wn_conj_gradient_method(&code,&val_min, vect,SIZE-1,(function),(gradient), WN_IHUGE); /* wn_conj_direction_method(&code,&val_min, vect,SIZE-1,(function), WN_IHUGE); */ printf("final result: code = %d ",code); printf(" ob = %lf\n",val_min); printf("total_count=%d,count=%d.\n",total_count,count); /* wn_print_vect(p,SIZE); { int i; double val; val = 1.0; for(i=0;i<SIZE-1;++i) { val -= vect[i]; } vect[SIZE-1] = val; } wn_print_vect(vect,SIZE); { int i; for(i=0;i<SIZE-1;++i) { printf("%lf ",p[i]/(vect[i]*vect[i])); } } */ wn_gpfree(); }