📄 bfagent.m
字号:
[to setSpecfactor: [from getSpecfactor]];
[to setLastactive: [from getLastactive]];
[to setSpecificity: [from getSpecificity]];
[to setConditions: [from getConditions]];
[to setCnt: [from getCnt]];
if ( [from getCnt] ==0)
[to setStrength: minstrength];
return to;
}
/*"Given a list of forecasts, find the worst ones and put them into a
pool of rejects. This method requires 2 inputs, the name of the reject
list (actually, a Swarm Array) and the Array of forecasts. "*/
- (void)MakePool: (id <List>)rejects From: (id <Array>)list
{
register int top;
int i,j = 0 ;
BFCast * aForecast;
BFCast * aReject;
top = -1;
//pj: why not just start at 1 so we never worry about putting forecast 0 into the mix?
for ( i=1; i < getInt(privateParams,"npool" ); i++ )
{
aForecast=[list atOffset: i];
for ( j=top; j >= 0 && (aReject=[rejects atOffset:j])&& ([aForecast getStrength] < [aReject getStrength] ); j--)
{
[rejects atOffset: j+1 put: aReject ];
} //note j decrements at the end of this loop
[rejects atOffset: j+1 put: aForecast];
top++;
}
for ( ; i < getInt(privateParams,"numfcasts"); i++)
{
aForecast=[list atOffset: i];
if ( [aForecast getStrength] < [[ rejects atOffset: top] getStrength ] )
{
for ( j = top-1; j >= 0 && (aReject=[rejects atOffset:j]) && [aForecast getStrength] < [aReject getStrength]; j--)
{
[rejects atOffset: j+1 put: aReject];
}
}
[rejects atOffset: j+1 put: aForecast];
}
//pj:note: we are not checking to see if forecast 0 is in here
}
/*------------------------------------------------------*/
/* Tournament */
/*------------------------------------------------------*/
- (BFCast *) Tournament: (id <Array>) list
{
int numfcasts=[list getCount];
BFCast * candidate1 = [list atOffset: irand(numfcasts)];
BFCast * candidate2;
do
candidate2 = [list atOffset: irand(numfcasts)];
while (candidate2 == candidate1);
if ([candidate1 getStrength] > [candidate2 getStrength])
return candidate1;
else
return candidate2;
}
/*------------------------------------------------------*/
/* Mutate */
/*------------------------------------------------------*/
- (BOOL)Mutate: (BFCast *)new Status: (BOOL)changed
/*
* For the condition bits, Mutate() looks at each bit with
* probability pmutation. If chosen, a bit is changed as follows:
* 0 -> * with probability 2/3, 1 with probability 1/3
* 1 -> * with probability 2/3, 0 with probability 1/3
* * -> 0 with probability 1/3, 1 with probability 1/3,
* unchanged with probability 1/3
* This maintains specificity on average.
*VERY CONFUSING, because the values are actually 0,1, and 2
CONVERTED LIKE SO
0 1 1/3 2 1/3
1 0 2/3 2 1/3
2 0 2/3 1 1/3
*
* For the forecasting parameters, Mutate() may do one of two things,
* independently for each parameter.
* 1. "Long jump": the parameter is chosen randomly from its min-max
* range.
* 2. "Short jump": the parameter is chosen randomly from a uniform
* distribution from oldvalue-nhood*range to oldvalue+nhood*range,
* where range = max-min. Values outside the min-max range are
* mapped to the endpoint.
* Method 1 is used with probability plong, method 2 is used with
* probability pshort, and the parameter is left unchanged with
* probability 1-plong-pshort.
*
* Returns YES if it actually changed anything, otherwise NO.
*/
{
register int bit;
double choice, temp;
BOOL bitchanged = NO;
int * bitlist= NULL;
bitlist= [privateParams getBitListPtr];
//pj: dont know why BFagents introduced bitchanged.??
bitchanged = changed;
if (privateParams->pmutation > 0)
{
for (bit = 0; bit < privateParams->condbits; bit++)
{
if (bitlist[bit] < 0) continue;
if (drand() < privateParams->pmutation)
{
//cond = cond0 + WORD(bit);
//if (*cond & MASK[bit])
if ([new getConditionsbit: bit] > 0 )
{
if (irand(3) > 0)
{
// *cond &= NMASK[bit];
//nr->specificity--;
[new maskConditionsbit: bit];
[new decrSpecificity];
}
else
// *cond ^= MASK[bit];
[new switchConditionsbit: bit];
bitchanged = changed = YES;
}
else if (irand(3) > 0)
{
// *cond |= (irand(2)+1) << SHIFT[bit];
// nr->specificity++;
[new setConditionsbit: bit FromZeroTo: (irand(2)+1)];
[new incrSpecificity];
bitchanged = changed = YES;
}
}
}
}
/* mutate p+d coefficient */
choice = drand();
if (choice < privateParams->plong)
{
/* long jump = uniform distribution between min and max */
[new setAval: privateParams->a_min + privateParams->a_range*drand()] ;
changed = YES;
}
else if (choice < privateParams->plong + privateParams->pshort)
{
/* short jump = uniform within fraction nhood of range */
temp = [new getAval] + privateParams->a_range*privateParams->nhood*urand();
[new setAval: (temp > privateParams->a_max? privateParams->a_max:
(temp < privateParams->a_min? privateParams->a_min: temp))];
changed = YES;
}
/* else leave alone */
/* mutate dividend coefficient */
choice = drand();
if (choice < privateParams->plong)
{
/* long jump = uniform distribution between min and max */
[new setBval: privateParams->b_min + privateParams->b_range*drand() ];
changed = YES;
}
else if (choice < privateParams->plong + privateParams->pshort)
{
/* short jump = uniform within fraction nhood of range */
temp = [new getBval] + privateParams->b_range*privateParams->nhood*urand();
[new setBval: (temp > privateParams->b_max? privateParams->b_max:
(temp < privateParams->b_min? privateParams->b_min: temp))];
changed = YES;
}
/* else leave alone */
/* mutate constant term */
choice = drand();
if (choice < privateParams->plong)
{
/* long jump = uniform distribution between min and max */
[new setCval: privateParams->c_min + privateParams->c_range*drand()];
changed = YES;
}
else if (choice < privateParams->plong + privateParams->pshort)
{
/* short jump = uniform within fraction nhood of range */
temp = [new getCval] + privateParams->c_range*privateParams->nhood*urand();
[new setCval: (temp > privateParams->c_max? privateParams->c_max:
(temp < privateParams->c_min? privateParams->c_min: temp))];
changed = YES;
}
/* else leave alone */
[new setCnt: 0];
if (changed)
{
[new updateSpecfactor];
}
return(changed);
}
/*------------------------------------------------------*/
/* Crossover */
/*------------------------------------------------------*/
- (BFCast *)Crossover: (BFCast *)newForecast Parent1: (BFCast *)parent1 Parent2: (BFCast *)parent2
/*
* On the condition bits, Crossover() uses uniform crossover -- each
* bit is chosen randomly from one parent or the other.
* For the real-valued forecasting parameters, Crossover() does
* one of three things:
* 1. Choose a linear combination of the parents' parameters,
* weighted by strength.
* 2. Choose each parameter randomly from each parent.
* 3. Choose one of the parents' parameters (all from one or all
* from the other).
* Method 1 is chosen with probability plinear, method 2 with
* probability prandom, method 3 with probability 1-plinear-prandom.
*/
{
/* Uniform crossover of condition bits */
register int bit;
// unsigned int *cond1, *cond2, *newcond;
int word;
double weight1, weight2, choice;
[newForecast setSpecificity: 0];
for (word = 0; word <privateParams->condwords; word++)
[newForecast setConditionsWord: word To: 0];
for (bit = 0; bit < privateParams->condbits; bit++)
{
if ( irand(2) == 0)
{
int value=[parent1 getConditionsbit: bit];
[newForecast setConditionsbit: bit FromZeroTo: value];
if (value > 0) [newForecast incrSpecificity];
}
else
{
int value= [parent2 getConditionsbit: bit];
[newForecast setConditionsbit: bit FromZeroTo: value ];
if (value > 0) [newForecast incrSpecificity];
}
}
/* Select one crossover method for the forecasting parameters */
choice = drand();
if (choice < privateParams->plinear)
{
/* Crossover method 1 -- linear combination */
weight1 = [parent1 getStrength] / ([parent1 getStrength] +
[parent2 getStrength]);
weight2 = 1.0-weight1;
[ newForecast setAval: weight1*[parent1 getAval] + weight2*[parent2 getAval] ];
[ newForecast setBval: weight1*[parent1 getBval] + weight2*[parent2 getBval] ];
[ newForecast setCval: weight1*[parent1 getCval] + weight2*[parent2 getCval]] ;
}
else if (choice < privateParams->plinear + privateParams->prandom)
{
/* Crossover method 2 -- randomly from each parent */
if(irand(2))
[newForecast setAval: [parent1 getAval]] ; else [newForecast setAval: [parent2 getAval]];
if(irand(2))
[newForecast setBval: [parent1 getBval]] ; else [newForecast setBval: [parent2 getBval]];
if(irand(2))
[newForecast setCval: [parent1 getCval]] ; else [newForecast setCval: [parent2 getCval]];
}
else
{
/* Crossover method 3 -- all from one parent */
if (irand(2))
{
[newForecast setAval: [parent1 getAval]] ;
[newForecast setBval: [parent1 getBval]] ;
[newForecast setCval: [parent1 getCval]] ;
}
else
{
[newForecast setAval: [parent2 getAval]] ;
[newForecast setBval: [parent2 getBval]] ;
[newForecast setCval: [parent2 getCval]] ;
}
}
{ //This is just error checking!
BitVector * newcond;
int specificity=0;
[newForecast setCnt: 0 ]; // call it new in any case
[newForecast updateSpecfactor];
[newForecast setStrength : 0.5*([parent1 getStrength] + [parent2 getStrength])];
//pj: next steps are purely diagnostic!
newcond = [newForecast getConditionsObject];
for (bit = 0; bit < privateParams->condbits; bit++)
//if ((newcond[WORD(bit)]& ( 3 << ((bit%16)*2))) != 0)
if ( [newcond getConditionsbit: bit] != 0 )
{
specificity++;
}
//printf("CrossoverDiagnostic: newforecast Specificity %d should equal %d \n", [newForecast getSpecificity],specificity);
}
return newForecast;
}
/*------------------------------------------------------*/
/* TransferFcasts */
/*------------------------------------------------------*/
- (void)TransferFcastsFrom: newlist To: forecastList Replace: rejects
{
id ind;
BFCast * aForecast;
BFCast * toDieForecast;
//nnew = pp->nnew;
ind = [newlist begin: [self getZone]];
for ( aForecast = [ind next]; [ind getLoc]==Member; aForecast=[ind next] )
{
//toDieForecast = GetMort(aForecast, rejects);
toDieForecast = [self GetMort: aForecast Rejects: rejects];
toDieForecast = [self CopyRule: toDieForecast From: aForecast];
}
[ind drop];
}
/*------------------------------------------------------*/
/* GetMort */
/*------------------------------------------------------*/
- (BFCast *)GetMort: (BFCast *)new Rejects: (id <List>)rejects
/* GetMort() selects one of the npool weak old fcasts to replace
* with a newly generated rule. It pays no attention to strength,
* but looks at similarity of the condition bits -- like tournament
* selection, we pick two candidates at random and choose the one
* with the MORE similar bitstring to be replaced. This maintains
* more diversity.
*/
{
//register int bit, temp1, temp2, different1, different2;
// struct BF_fcast *fptr;
//unsigned int *cond1, *cond2, *newcond;
//int npool, r1, r2, word, bitmax;
unsigned int *cond1; unsigned int *cond2; uns
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -