Пример #1
0
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);
}
Пример #2
0
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);
  }
}
Пример #3
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 */
Пример #4
0
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);
  }
}
Пример #5
0
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);
}
Пример #6
0
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();
}
Пример #7
0
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;
  }
}
Пример #8
0
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;
}
Пример #9
0
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();
}