int adapt()

in masses/garescorer.c [474:670]


int adapt(PGAContext *ctx, int p, int pop, int done_eval, int threshold,
	  int repeat) {
  double *myscores;
  int i;
  int changed = 0;
  double tmp,old_evaluation,new_evaluation;

  if (justCount) {
    return 0;
  }

  adapt_times++;

  if (done_eval && PGAGetEvaluationUpToDateFlag(ctx, p, pop))
    old_evaluation = PGAGetEvaluation(ctx, p, pop);
  else {
    old_evaluation = evaluate(ctx, p, pop);
    PGASetEvaluation(ctx, p, pop, old_evaluation);
    PGASetEvaluationUpToDateFlag(ctx, p, pop, PGA_TRUE);
  }

  if ((double)ga_yn > ((double)ga_ny*nybias))
    weight_balance--;
  else if ((double)ga_yn < ((double)ga_ny*nybias))
    weight_balance++;

  if ((weight_balance < (threshold-1)) &&
      (weight_balance > -threshold))
    return 0;

  myscores = PGAGetIndividual(ctx, p, pop)->chrom;

  if (repeat) {
    for (i = 0; i < num_mutable; i++) {
      if ((yn_hit[i] && (weight_balance < 0)) ||
	  (ny_hit[i] && (weight_balance > 0))) {
	if (((weight_balance < 0) &&
#ifdef USE_SCORE_RANGES
	     (myscores[i] < range_hi[i]) &&
#endif
	     (myscores[i] < -(double)0.01)) ||
	    ((weight_balance > 0) &&
#ifdef USE_SCORE_RANGES
	     (myscores[i] > range_lo[i]) &&
#endif
	     (myscores[i] > (double)0.01))) {
          tmp_scores[i][0] = (double)0.001*rint(myscores[i]); /* reducing */
#ifdef USE_SCORE_RANGES
	  if (((myscores[i] < -(double)0.01) && ((myscores[i] - tmp_scores[i][0]) > range_hi[i])) ||
	      ((myscores[i] > (double)0.01) && ((myscores[i] - tmp_scores[i][0]) < range_lo[i]))) {
	    tmp_scores[i][0] = 0;
	  }
#endif
	  if (tmp_scores[i][0]) {
	    changed = 1;
	    lookup[i] = 0;
	  }
	} else
	  tmp_scores[i][0] = 0;
      } else
	tmp_scores[i][0] = 0;
    }

    if (! changed)		/* if can't reduce, don't do anything - safe */
      return 0;

    /* For every message */
    for (i=num_nondup-1; i>=0; i--) {
      tmp_total[i] = scores[i];
      scores[i] =
	score_msg(ctx,p,pop,i)/tests_count[i]; /* score sans ones modifying */
    }

    for (i = 0; i < num_mutable; i++) {
      if (tmp_scores[i][0]) {
	lookup[i] = myscores[i];
	tmp_scores[i][1] = 1;
	if (weight_balance < 0) {
	  yn_hit[i] = 1;
	  ny_hit[i] = 0;
	} else {
	  ny_hit[i] = 1;
	  yn_hit[i] = 0;
	}
      } else {
	lookup[i] = 0;
	tmp_scores[i][1] = 0;
	yn_hit[i] = ny_hit[i] = 0;
      }
    }

    new_evaluation = old_evaluation;  /* avoid a warning */
    while (1) {
      changed = 0;
      for (i = 0; i < num_mutable; i++) {
	if (((tmp_scores[i][0] < 0) && yn_hit[i] && /* going up */
#ifdef USE_SCORE_RANGES
             ((lookup[i] - tmp_scores[i][0]) < range_hi[i]) &&
#endif
             (weight_balance < 0) && (lookup[i] < -(double)0.01)) ||
	    ((tmp_scores[i][0] > 0) && ny_hit[i] && /* going down */
#ifdef USE_SCORE_RANGES
             ((lookup[i] - tmp_scores[i][0]) > range_lo[i]) &&
#endif
	     (weight_balance > 0) &&
             (lookup[i] > (double)0.01))) {
	  lookup[i] -= tmp_scores[i][0];
	  changed = 1;
	} else
	  tmp_scores[i][0] = 0;
	yn_hit[i] = ny_hit[i] = 0;
      }

      if (changed) {
	if (weight_balance > 0)
	  adapt_ny++;
	else
	  adapt_yn++;
	adapt_repeat++;
      } else
	break;

      yyscore = ynscore = nyscore = nnscore = 0.0;
      ga_yy=ga_yn=ga_ny=ga_nn=0;

      for (i=num_nondup-1; i>=0; i--)
	(void)score_msg(ctx,p,pop,i);

      new_evaluation = evaluate_inner();

      if (new_evaluation > old_evaluation) {
	for (i = 0; i < num_mutable; i++) {
	  if (tmp_scores[i][0])
	    lookup[i] += tmp_scores[i][0];
	}
	new_evaluation = old_evaluation;
	adapt_overshot++;
	break;
      } else
	old_evaluation = new_evaluation;

      if ((double)ga_yn > ((double)ga_ny*nybias))
	weight_balance--;
      else if ((double)ga_yn < ((double)ga_ny*nybias))
	weight_balance++;
      
      if ((weight_balance < (threshold-1)) &&
	  (weight_balance > -threshold))
	break;
    }
    for (i=num_nondup-1; i>=0; i--)
      scores[i] = tmp_total[i];

    for (i=0; i < num_mutable; i++) {
      if (tmp_scores[i][1])
	myscores[i] = lookup[i];
    }

    PGASetEvaluation(ctx, p, pop, new_evaluation);
    PGASetEvaluationUpToDateFlag(ctx, p, pop, PGA_TRUE);

    return 1;
  } else {
    for (i = 0; i < num_mutable; i++) {
      if ((yn_hit[i] && (weight_balance < 0)) ||
	  (ny_hit[i] && (weight_balance > 0))) {
        tmp = (double)0.001*rint(myscores[i]);
	if (! tmp) {
	  if (myscores[i] > (double)0.01)
            tmp = (double)0.001;
	  else if (myscores[i] < -(double)0.01)
            tmp = -(double)0.001;
	}
#ifdef USE_SCORE_RANGES
	if (tmp && (((myscores[i] > 0) &&
		     ((myscores[i] - tmp) < range_lo[i])) ||
		    ((myscores[i] < 0) &&
		     ((myscores[i] - tmp) > range_hi[i]))))
	  tmp = 0;
#endif
	if (tmp) {
	  myscores[i] -= tmp;
	  changed = 1;
	}
      }
    }
    
    if (changed) {
      if (weight_balance > 0)
	adapt_ny++;
      else
	adapt_yn++;
      return 1;
    } else
      return 0;
  }
}