예제 #1
0
int main(void)
{
  double *vect1,*vect2,*vect3;

  wn_gpmake("general_free");

  wn_make_vect(&vect1,LEN);
  wn_make_vect(&vect2,LEN);
  wn_make_vect(&vect3,LEN);

  wn_random_vect(vect1,LEN);
  wn_print_vect(vect1,LEN);
  wn_copy_vect(vect2,vect1,LEN);
  wn_print_vect(vect1,LEN);
  wn_random_vect(vect2,LEN);

  printf("v1.v2 = %lf\n",wn_dot_vects(vect1,vect2,LEN));
  printf("v1.v1 = %lf\n",wn_dot_vects(vect1,vect1,LEN));
  printf("norm2(v1) = %lf\n",wn_norm2_vect(vect1,LEN));
  printf("norm(v1) = %lf\n",wn_norm_vect(vect1,LEN));
  printf("corr(v1,v2)) = %lf\n",
	 wn_dot_vects(vect1,vect2,LEN)/
	 (wn_norm_vect(vect1,LEN)*wn_norm_vect(vect2,LEN)));

  wn_free_vect(vect1,LEN);

  wn_gpfree();

  return(0);
}
예제 #2
0
void wn_cdn_set_solution
(
  wn_cdn_context_type c,
  double vect[]
)
{
  wn_copy_vect(c->current_vect,vect,c->num_vars);
}
예제 #3
0
/********************************************************************
Fit traditional cubic to  2 points (x,y) and derivatives
Cubic is of the form

  y = c3*x^3 + c2*x^2 + c1*x + c0

Return c3, c2, c1, c0
********************************************************************/
void wn_fit_cubic_2p2d
(
  int *pcode,
  double coef[4],
  double x1,double y1,double dy1,
  double x2,double y2,double dy2
)
{
  double c[4];
  double m,b;
  double xform[2];
  double accum[5],next_accum[5];
  int i,j;

  *pcode = WN_SUCCESS;

  if(x1 == x2)
  {
    *pcode = WN_SINGULAR;
    return;
  }

  /* compute mapping from x space to -1 +1 space */
  m = 2.0/(x2-x1);
  b = 1.0 - m*x2;

  dy1 /= m;
  dy2 /= m;

  /* compute coefs assuming x1==-1,x2==1 */
  c[2] = (1.0/4.0)*(dy2-dy1);
  c[0] = (1.0/2.0)*(y2+y1) - c[2];
  c[3] = (1.0/2.0)*(y1+dy1 + c[2] - c[0]);
  c[1] = dy2 - 3.0*c[3] - 2.0*c[2];

  /* use mapping to transform cubic */
  wn_zero_vect(coef,4);
  wn_zero_vect(accum,4);
  accum[0] = 1.0;

  xform[0] = b;
  xform[1] = m;

  for(i=0;i<4;++i)
  {
    for(j=0;j<=i;++j)
    {
      coef[j] += c[i]*accum[j];
    }

    wn_mult_polys(next_accum,accum,i+1,xform,2);
    wn_copy_vect(accum,next_accum,i+2);
  }

  *pcode = WN_SUCCESS;
}
예제 #4
0
void wn_cdn_compute_func_call_vect
(
  wn_cdn_context_type c,
  double *search_direction,
  double x
)
{
  wn_copy_vect(c->func_call_vect,c->current_vect,c->num_vars);
  wn_add_scaled_vect(c->func_call_vect,search_direction,x,c->num_vars);
}
예제 #5
0
void wn_cdn_get_solution
(
  wn_cdn_context_type c,
  int *pcode,
  double *pob,
  double vect[]
)
{
  *pcode = c->code;
  *pob = c->ob;
  wn_copy_vect(vect,c->current_vect,c->num_vars);
}
예제 #6
0
local double line_function(double x)
{
  double ret;

  if(last_line_function_x_valid)
  {
    if(x == last_line_function_x)
    {
      return(last_line_function_ret);
    }
  }

  wn_copy_vect(save_vect,buffer_vect,num_vars);
  wn_add_scaled_vect(save_vect,save_direction,x,num_vars);

  if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL)
  {
    printf("function call %d at ",num_func_calls);
    wn_print_vect(save_vect,num_vars);
  }

  ++num_func_calls;

  ret = wn_clip_f((*save_pfunction)(save_vect));

  if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL)
  {
    printf("function value is %lg\n",ret);
    fflush(stdout);
  }

  last_line_function_x_valid = TRUE;
  last_line_function_x = x;
  last_line_function_ret = ret;

  return(ret);
}
예제 #7
0
EXTERN void wn_conj_direction_method
(
  int *pcode,
  double *pval_min,
  double vect[],
  double initial_coord_x0s[],
  int passed_num_vars,
  double (*pfunction)(double vect[]),
  int max_func_calls
)
{
  int i,j,iteration;
  double *old_vect,*coord_direction;
  double *new_search_direction;
  double old_val_min;

  wn_memgp conj_dir_memgp;

  wn_gpmake("no_free");

  force_optimize_stop_flag = FALSE;

  num_vars = passed_num_vars;
  max_num_search_directions = num_vars;

  wn_make_vect(&buffer_vect,num_vars);
  search_directions = (double **)wn_zalloc(
		  max_num_search_directions*sizeof(double *));
  wn_make_vect(&old_vect,num_vars);
  wn_make_vect(&coord_direction,num_vars);
  wn_make_vect(&coord_x0s,num_vars);
  wn_make_vect(&search_direction_x0s,max_num_search_directions);
  wn_make_vect(&coord_as,num_vars);
  wn_make_vect(&search_direction_as,max_num_search_directions);
  if(initial_coord_x0s == NULL)
  {
    wn_zero_vect(coord_x0s,num_vars);
  }
  else
  {
    wn_copy_vect(coord_x0s,initial_coord_x0s,num_vars);
  }
  wn_zero_vect(search_direction_x0s,max_num_search_directions);
  wn_zero_vect(coord_as,num_vars);
  wn_zero_vect(search_direction_as,max_num_search_directions);

  /* name and pop the memory group we created */

  conj_dir_memgp = wn_curgp();
  wn_gppop();

  sqrt_tolerance = sqrt(wn_machine_tolerance());

  num_search_directions = 0;

  num_func_calls = 0;

  last_line_function_x_valid = FALSE;
  *pval_min = wn_clip_f((*pfunction)(vect));
  ++num_func_calls;

  for(iteration=0;;++iteration)
  {
    if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_PASSES)
    {
      printf("iteration = %d ********************************\n",iteration);
      printf("ob = %lg\n",*pval_min);
      fflush(stdout);
    }
    /*
    (void)getchar();
    */

    old_val_min = *pval_min;
    wn_copy_vect(old_vect,vect,num_vars);

    /* minimize along acceleration search directions */
    if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH)
    {
      printf("start acceleration line minimizations ------------------\n");
    }
    for(i=0;i<num_search_directions;++i)
    {
      if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH)
      {
        printf("acceleration line search %d\n",i);
      }

      line_minimize(vect,search_directions[i],pval_min,
		    &(search_direction_x0s[i]),&(search_direction_as[i]),
		    pfunction);

      if(
	  ((max_func_calls < WN_IHUGE)&&(num_func_calls > max_func_calls))
	    ||
          force_optimize_stop_flag
	)
      {
        *pcode = WN_SUBOPTIMAL;
	goto finish;
      }
    }

    /* minimize along coordinate directions */
    if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) 
    {
      printf("start coordinate line minimizations ------------------\n");
    }
    for(i=0;i<num_vars;++i)
    {
      if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH)
      {
        printf("coord line search %d\n",i);
      }

      coord_direction[i] = 1.0;

      line_minimize(vect,coord_direction,pval_min,
		    &(coord_x0s[i]),&(coord_as[i]),
		    pfunction);

      coord_direction[i] = 0.0;

      if(
	  ((max_func_calls < WN_IHUGE)&&(num_func_calls > max_func_calls))
	    ||
          force_optimize_stop_flag
	)
      {
        *pcode = WN_SUBOPTIMAL;
	goto finish;
      }
    }

    if(*pval_min >= old_val_min)
    {
      wn_assert(*pval_min == old_val_min);

      *pcode = WN_SUCCESS;
      break;
    }

    /* compute new acceleration search direction */
    if(num_search_directions < max_num_search_directions)
    {
      wn_gppush(conj_dir_memgp);
      wn_make_vect(&new_search_direction,num_vars);
      wn_gppop();
      for(i=num_search_directions;i>0;--i)
      {
        search_directions[i] = search_directions[i-1];
	search_direction_x0s[i] = search_direction_x0s[i-1];
	search_direction_as[i] = search_direction_as[i-1];
      }
      search_directions[0] = new_search_direction;
      search_direction_x0s[0] = 1.0;
      search_direction_as[0] = 0.0;

      ++num_search_directions;
    }
    else
    {
      new_search_direction = search_directions[max_num_search_directions-1];
      for(i=max_num_search_directions-1;i>0;--i)
      {
        search_directions[i] = search_directions[i-1];
	search_direction_x0s[i] = search_direction_x0s[i-1];
	search_direction_as[i] = search_direction_as[i-1];
      }
      search_directions[0] = new_search_direction;
      search_direction_x0s[0] = 1.0;
      search_direction_as[0] = 0.0;
    }

    for(j=0;j<num_vars;++j)
    {
      new_search_direction[j] = vect[j] - old_vect[j];
    }
  }

finish: ;

  force_optimize_stop_flag = FALSE;
  last_line_function_x_valid = FALSE;

  wn_gppush(conj_dir_memgp);
  wn_gpfree();
}
예제 #8
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);
  }
}
예제 #9
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);
}
예제 #10
0
void wn_cdn_optimize
(
  wn_cdn_context_type c,
  int num_func_calls
)
{
  int i,j,iteration;
  double *old_vect,*coord_direction;
  wn_cdn_srchdir_type new_search_direction;
  double old_ob;
  double x_width_sum;

  wn_gppush(c->current_group);

  c->force_optimize_stop_flag = FALSE;

  if(num_func_calls >= WN_IHUGE)
  {
    c->max_num_func_calls = WN_IHUGE;
  }
  else
  {
    c->max_num_func_calls = c->num_func_calls + num_func_calls;
  }

  if(c->code == WN_CDN_NOT_STARTED)
  {
    c->code = WN_SUBOPTIMAL;
    c->ob = wn_clip_f((*(c->pfunction))(c->current_vect,c->num_func_calls));
    ++(c->num_func_calls);
  }

  for(iteration=0;;++iteration)
  {
    /*
    if(wn_cdn_debug >= WN_CDN_DBG_PASSES)
    */
    {
      printf("iteration = %d ********************************\n",iteration);
      printf("num_func_calls = %d\n",c->num_func_calls);
      printf("ob = %lg\n",c->ob);
      printf("vect = \n");
      wn_print_vect(c->current_vect,c->num_vars);
      fflush(stdout);
    }
    /*
    (void)getchar();
    */

    old_ob = c->ob;
    wn_copy_vect(c->old_vect,c->current_vect,
                 c->num_vars);
    x_width_sum = 0.0;

    /* minimize along acceleration search directions */
    if(wn_cdn_debug >= WN_CDN_DBG_LINESEARCH)
    {
      printf("start acceleration line minimizations ------------------\n");
    }
    for(i=0;i<c->num_search_directions;++i)
    {
      if(wn_cdn_debug >= WN_CDN_DBG_LINESEARCH)
      {
        printf("acceleration line search %d\n",i);
      }

      line_minimize(c,(c->search_direction_array)[i],&x_width_sum);

      if(
	  (
            (c->max_num_func_calls < WN_IHUGE)
              &&
            (c->num_func_calls > c->max_num_func_calls)
          )
	    ||
          c->force_optimize_stop_flag
	)
      {
        c->code = WN_SUBOPTIMAL;
	goto finish;
      }
    }

    /* minimize along coordinate directions */
    if(wn_cdn_debug >= WN_CDN_DBG_LINESEARCH) 
    {
      printf("start coordinate line minimizations ------------------\n");
    }
    for(i=0;i<c->num_vars;++i)
    {
      if(wn_cdn_debug >= WN_CDN_DBG_LINESEARCH)
      {
        printf("coord line search %d\n",i);
      }

      line_minimize(c,(c->coord_search_direction_array)[i],&x_width_sum);

      if(
	  (
            (c->max_num_func_calls < WN_IHUGE)
              &&
            (c->num_func_calls > c->max_num_func_calls)
          )
	    ||
          c->force_optimize_stop_flag
	)
      {
        c->code = WN_SUBOPTIMAL;
	goto finish;
      }
    }

    recompute_num_line_samples(c);

    if(!vects_equal(c->current_vect,c->old_vect,c->num_vars))
    {
      /* compute new acceleration search direction */
      if(c->num_search_directions < c->max_num_search_directions)
      {
        make_search_direction(c,&new_search_direction,FALSE,-1);
        for(i=c->num_search_directions;i>0;--i)
        {
          (c->search_direction_array)[i] = 
              (c->search_direction_array)[i-1];
        }
        (c->search_direction_array)[0] = new_search_direction;

        ++(c->num_search_directions);
      }
      else
      {
        new_search_direction = 
          (c->search_direction_array)[(c->max_num_search_directions) - 1];
        reset_search_direction(c,new_search_direction);
        for(i=c->max_num_search_directions-1;i>0;--i)
        {
          (c->search_direction_array)[i] = 
              (c->search_direction_array)[i-1];
        }
        (c->search_direction_array)[0] = new_search_direction;
      }

      for(j=0;j<c->num_vars;++j)
      {
        (new_search_direction->dir_vect)[j] = 
	    (c->current_vect)[j] - (c->old_vect)[j];
      }

      new_search_direction->x0 = 1.0;
      new_search_direction->x_width = 1.0/x_width_sum;
      new_search_direction->max_x_width = 100.0*new_search_direction->x_width;
    }
  }

finish: ;

  c->force_optimize_stop_flag = FALSE;

  wn_gppop();
}
예제 #11
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;
  }
}
예제 #12
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;
}