⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bfagent.m

📁 人工智能的matlab程序
💻 M
📖 第 1 页 / 共 5 页
字号:
  condition bits set to 00 here, meaning "don't care.  It also sets
  values for the other coefficients inside the BFCast.  This method is
  accessed at several points throughout the BFagent class when new
  forecasts are needed."*/
- (BFCast *)createNewForecast
{
  BFCast * aForecast;
  //needed to set values of a,b,and c
  double abase = privateParams->a_min + 0.5*(1.0-privateParams->subrange)*privateParams->a_range;
  double bbase = privateParams->b_min + 0.5*(1.0-privateParams->subrange)*privateParams->b_range;
  double cbase = privateParams->c_min + 0.5*(1.0-privateParams->subrange)*privateParams->c_range;
  double asubrange = privateParams->subrange*privateParams->a_range;
  double bsubrange = privateParams->subrange*privateParams->b_range;
  double csubrange = privateParams->subrange*privateParams->c_range;

  aForecast= [BFCast createBegin: [self getZone]]; 
  [aForecast setCondwords: privateParams->condwords];
  [aForecast setCondbits: privateParams->condbits];
  [aForecast setNNulls: privateParams->nnulls];
  [aForecast setBitcost: privateParams->bitcost];
  aForecast = [aForecast createEnd];
  [aForecast setForecast: 0.0];
  [aForecast setLforecast: global_mean];
  //note aForecast has the forecast conditions=0 by its own createEnd.
  //also inside its createEnd, lastactive =1, specificity=0, variance=99999;

  //pj: Controversy/confusion BFagent.m as originally distributed used
  //definitions for variance and strength that did not match the
  //bfagent.m file or the documentation. I'm following bfagent.m and
  //the docs, ignoring what was in BFagent.m

  [aForecast setVariance: privateParams->newfcastvar];  //same as bfagent's init  
  [aForecast setStrength: 0.0];
     
  /* Set the forecasting parameters for each fcast to random values in a
   * fraction "subrange" of their range, centered at the midpoint.  For
   * subrange=1 this is the whole range (min to max).  For subrange=0.5,
   * values lie between 1/4 and 3/4 of this range.  subrange=0 gives
   * homogeneous agents, with values at the middle of their min-max range. 
   */
  [aForecast setAval : abase + drand()*asubrange];
  [aForecast setBval : bbase + drand()*bsubrange];
  [aForecast setCval : cbase + drand()*csubrange];

  return aForecast;   
}

/*"Take a forecast object and randomly change the bits that govern
  which conditions it monitors.  This appears to be a piece of
  functionality that could move to the BFCast class itself. There were
  quite a few of these details floating around in BFagent at one time,
  many are gone now."*/
- setConditionsRandomly: (BFCast *)fcastObject
{
  int bit;
  double *problist;
  int *bitlist;

  bitlist = [privateParams getBitListPtr];
 
  problist = [privateParams getProbListPtr];

  for(bit=0; bit< privateParams->condbits; bit++)
    {
      if (bitlist[bit] < 0)
	{
	  [fcastObject setConditionsbit: bit FromZeroTo: 3];//3=11 is a "filler"
	}
      else if (drand() < problist[bit])
	{  
	  [fcastObject setConditionsbit: bit FromZeroTo:  irand(2)+1];
	  //remember 1 means no, or binary 01, and 2 means Yes, or 10
	  [fcastObject incrSpecificity];//pj: I wish this were automatic!
	  [fcastObject updateSpecfactor];
	}
    }
  return self;
}


- prepareForTrading
  /*"
 * Set up a new active list for this agent's forecasts, and compute the
 * coefficients pdcoeff and offset in the equation
 *	forecast = pdcoeff*(trialprice+dividend) + offset
 *
 * The active list of all the fcasts matching the present conditions is saved
 * for later updates.
 "*/
{
  //register struct BF_fcast *fptr, *topfptr, **nextptr;
  //unsigned int real0, real1, real2, real3, real4 = 0 ;
  double weight, countsum, forecastvar=0.0;
  int mincount;
  int nactive;

  //pj: for getting values from world
  BitVector * myworld; 
 
  //for using indexes of forecast objects
  BFCast *  aForecast;
  id <Index> index;

#if  WEIGHTED == 1    
  static double a, b, c, sum, sumv;
#else
  //struct BF_fcast *bestfptr;
  BFCast *  bestForecast;
  double maxstrength;
#endif

 
  // First the genetic algorithm is run if due
  currentTime = getCurrentTime( );
     
  if (currentTime >= privateParams->firstgatime && drand() < privateParams->gaprob) 
    {
      [self performGA]; 
      [activeList removeAll];
    }	    

  //this saves a copy of the agent's last as lforecast.
  lforecast = forecast;
    
  myworld = [self collectWorldData: [self getZone] ];
  
  [self updateActiveList: myworld];

  [myworld drop]; //was created inside collectWorldData

 
#if WEIGHTED == 1
  // Construct weighted-average forecast
  // The individual forecasts are:  p + d = a(p+d) + b(d) + c
  // We often lock b at 0 by setting b_min = b_max = 0.

  //pj: note I started updating this code to match the rest, but then
  //pj: I realized it did not work as it was before, so I stopped
  //pj: messing with it. Don't expect the CPPFLAG WEIGHTED to do 
  //pj: anything good.

  a = 0.0;
  b = 0.0;
  c = 0.0;
  sumv = 0.0;
  sum = 0.0;
  nactive = 0;
  mincount = privateParams->mincount;

  index=[ activeList begin: [self getZone] ];
  for( aForecast=[index next]; [index getLoc]==Member; aForecast=[index next] )
    {
      [aForecast setLastactive: t];
      if ( [aForecast incrCount] >= mincount )
	{
	  double sumstrength;
	  double strength;
	  strength=[aForecast getStrength];
	  ++nactive;

  	  a += strength*[aForecast getAval];
  	  b += strength*[aForecast getBval] ;
  	  c += strength*[aForecast getCval] ;
  	  sum += strength;
  	  sumv += [aForecast getVariance];
	}
    }
  [index drop];

  if (nactive) 
    {
      pdcoeff = a/sum;
      offset = (b/sum)*dividend + (c/sum);
      forecastvar = privateParams->individual? sumv/((double)nactive) :variance;
    }
#else
  //NOT WEIGHTED MODEL
  // Go through the list and find best forecast
  maxstrength = -1e50;
  bestForecast = nil;
  nactive = 0;
  mincount = getInt(privateParams,"mincount");

  //pj: Kept as example of "homemade list" in ASM-2.0
  //    for (fptr=activelist; fptr!=NULL; fptr=fptr->next) 
  //      {
  //        fptr->lastactive = currentTime;
  //        if (++fptr->count >= mincount) 
  //  	{
  //  	  ++nactive;
  //  	  if (fptr->strength > maxstrength) 
  //  	    {
  //  	      maxstrength = fptr->strength;
  //  	      bestfptr = fptr;
  //  	    }
  //  	}
  //      }
  

  //??Following code causes a bug when numfcasts is small. It causes
  //nactive >0 even though there is no best forecast. ?? Track it down
  //This problem existed in ASM-2.0, should back track it.
  index=[activeList begin: [self getZone]];
  for( aForecast=[index next]; [index getLoc]==Member; aForecast=[index next] )
    {
      [aForecast setLastactive: currentTime];
      if([aForecast incrCount] >= mincount)
	{
	  double strength=[aForecast getStrength];
	  ++nactive;
	  if (strength > maxstrength)
	    {
	      maxstrength = strength;
	      bestForecast= aForecast;
	    }
	}
    }
  [index drop];

  // Here is the way it was in ASM-2.0
  //    if (nactive) 
  //      {
  //        pdcoeff = bestfptr->a;
  //        offset = bestfptr->b*dividend + bestfptr->c;
  //        forecastvar = (privateParams->individual? bestfptr->variance :variance);
  //      }
 
  if (nactive)  // meaning that at least some forecasts are active
    {
      pdcoeff = [bestForecast getAval];
      offset = [bestForecast getBval]*dividend + [bestForecast getCval];
      forecastvar = getInt(privateParams,"individual")? [bestForecast getVariance]: variance;
    }

#endif
  else  // meaning "nactive" zero, no forecasts are active 
    {
      // No forecasts are minimally adequate!!
      // Use weighted (by count) average of all rules
      countsum = 0.0;
      pdcoeff = 0.0;
      offset = 0.0;
      mincount = getInt(privateParams,"mincount");


      index = [fcastList begin: [self getZone]];
      for ( aForecast=[index next]; [index getLoc]==Member; aForecast=[index next] )
	{
	  if ([aForecast getCnt] >= mincount)
	    {  
	      countsum += weight = [aForecast getStrength];
	      offset += ([aForecast getBval]*dividend + [aForecast getCval])*weight;
	      pdcoeff += [aForecast getAval]*weight;
	    }
  
	  if (countsum > 0.0) 
	    {
	      offset /= countsum;
	      pdcoeff /= countsum;
	    }
	  else
	    {
	      offset = global_mean;
	    }
	  forecastvar = variance;
	}
      [index drop];
    }

  divisor = getDouble(privateParams,"lambda")*forecastvar;
    
  return self;
}

/*"A forecast has a set of conditions it is watching. These are packed
tight in a BitVector. We need the world data about the status of those
conditions packed the same way, in order to make quick checks to find
out if the world conditions are matched by the BitVector's
conditions. This method creates a BitVector to match the conditions
that are being monitored by the agent's forecasts.  This requires the
use of the design assumption that all of an agent's forecasts have the
same bitlist."*/
- (BitVector *)collectWorldData: aZone;
{ 
  int i,n,nworldbits;
  BitVector * world;
  int * bitlist;
  int * myRealWorld=NULL;

  
  world= [BitVector createBegin: aZone];
  [world setCondwords: params->condwords];
  [world setCondbits: params->condbits];
  world=[world createEnd];
    
  bitlist = [params getBitListPtr];
  nworldbits = [worldForAgent getNumWorldBits];

  myRealWorld = [aZone alloc: nworldbits*sizeof(int)];
  
  [worldForAgent getRealWorld: myRealWorld];

  for (i=0; i < params->condbits; i++) 
    {
      if ((n = bitlist[i]) >= 0)
	//myworld[WORD(i)] |= myRealWorld[n] << ((i%16)*2);
	[world setConditionsbit: i To: myRealWorld[n]]; 
    }

  [aZone free: myRealWorld];

   return world;
}


/*"This is the main inner loop over forecasts. Go through the list
  of active forecasts, compare how they did against the world.  Notice
  the switch that checks to see how big the bitvector (condwords) is
  before proceeding.  At one time, this gave a significant
  speedup. The original sfsm authors say 'Its ugly, but it
  works. Don't mess with it!'  (pj: I've messed with it, and don't
  notice much of a speed effect on modern computers with modern
  compilers :> My alternative implementation is commented out inside
  this method)"*/
- updateActiveList: (BitVector *)worldvalues
{
  id index;
  BFCast * aForecast;
 
  [self copyList: activeList To: oldActiveList]; 
  //pj: note, if activeList is empty, then oldActiveList will be empty.
  
  [activeList removeAll];


  //pj:copy forecasted values from objects in active to oldActiveList
  index=[ oldActiveList begin: [self getZone] ];
    for( aForecast=[index next]; [index getLoc]==Member; aForecast=[index next] )
      {
      [aForecast setLforecast: [aForecast getForecast]];
      }
    [index drop];


  switch (privateParams->condwords) {
  case 1:

    index=[ fcastList begin: [self getZone]];
    for ( aForecast=[index next]; [index getLoc]==Member; aForecast=[index next] )
    {
      if ( [aForecast getConditionsWord: 0] & [worldvalues getConditionsWord: 0] ) 
	 {
 	   continue ;
	 }
      [activeList addLast: aForecast];
    }
    [index drop];

    break;
  
    case 2:
      //pj: here is how it used to be in ASM-2.0
//      real1 = worldvalues[1];

//      for (fptr = fcast; fptr < topfptr; fptr++) 
//        {
//  	if (fptr->conditions[0] & real0) continue;
//  	if (fptr->conditions[1] & real1) continue;
//  	*nextptr = fptr;
//  	nextptr = &fptr->next;
//        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -