📄 cmac.cpp
字号:
#include <stdlib.h>
#include <fcntl.h>
#include <io.h>
#include <sys\stat.h>
#include <malloc.h>
#include "unh_cmac.h"
#define TRUE 1
#define FALSE 0
#define NUM_CMACS 8
#define MAX_STATE_SIZE 64
#define MAX_RESPONSE_SIZE 8
#define MAX_GEN_SIZE 256
#define RF_TABLE_SIZE 128
static int first_call=TRUE; /* is set to FALSE after init */
static int in_learn=FALSE; /* is set to TRUE while in learn */
static int *ap_a[NUM_CMACS+1]; /* pointers to all cmac memories */
static int *ap; /* pointer to current cmac memory */
static int ap_size[NUM_CMACS+1]; /* sizes in bytes of cmac memories */
static int rsp_size; /* dimension of response vector */
static int gen_size; /* generalization parameter */
static int st_size; /* dimension of input state vector */
static int mem_size; /* # of response vectors in memory */
static int rf_shape; /* code for the receptive field shape */
static int collide; /* TRUE/FALSE control of hash collisions */
static int *qnt; /* pointer to input quantization */
static int *disp; /* pointer to the displacement vector */
static int *rfieldt; /* pointer to the rfield function table */
static unsigned int rndseq[2048]; /* Random number table for hashing */
static unsigned int rndseq2[2048]; /* Random number table for hashing */
static int indexes[MAX_GEN_SIZE]; /* CMAC mapping indexes */
static long rfield[MAX_GEN_SIZE]; /* RF function magnitudes */
static long sum_rfield = 0; /* summed RF function magnitudes */
static long sum2_rfield = 0; /* summed squared RF function magnitudes */
static void stoap(int *state)
{
int i,j,k;
long index,min_d,test_d,rf_index;
long sum;
int hash_tag;
static long base[MAX_STATE_SIZE],qstate[MAX_STATE_SIZE];
if((rf_shape==ALBUS)||(rf_shape==RECTANGULAR))
{
for(i=0;i<st_size;i++)
{
if(state[i]>=0)
{
qstate[i]=state[i]/qnt[i];
}
else
{
qstate[i]=(state[i]-qnt[i]+1)/qnt[i];
}
base[i]=0;
}
for(j=0;j<gen_size;j++)
{
sum = 0;
hash_tag = 0;
for(i=0;i<st_size;i++)
{
if(qstate[i]>=base[i])
index=qstate[i]-((qstate[i]-base[i])%gen_size);
else
index=(qstate[i]+1)+((base[i]-(qstate[i]+1))%gen_size)-gen_size;
index+=(449*i);
index%=2048;
while(index<0)
index+=2048;
sum+=(long)rndseq[(int)index];
if(!collide)
hash_tag+=(int)rndseq2[(int)index];
base[i]+=disp[i];
}
if(hash_tag==0)
hash_tag=1;
indexes[j]=(int)(sum%mem_size);
while(indexes[j]<0)
indexes[j]+=mem_size;
if(!collide)
{
--indexes[j];
k=0;
i=(indexes[j]*(rsp_size+1))+rsp_size;
do
{
if(++indexes[j]>=mem_size)
{
indexes[j]=0;
i=rsp_size;
}
else
{
i+=rsp_size+1;
}
}while((ap[i]!=hash_tag)&&(ap[i]!=0)&&(++k<mem_size));
}
else
{
i=(indexes[j]*(rsp_size+1))+rsp_size;
}
if((in_learn)&&(ap[i]==0))
ap[i]=hash_tag;
}
return;
}
for(i = 0; i < st_size; i++)
{
if(state[i]>=0)
{
qstate[i]=(long)(state[i] / qnt[i]);
}
else
{
qstate[i] = (long)((state[i] - qnt[i] + 1) / qnt[i]);
}
base[i] = 0; /* first RF layer aligned with origen */
}
/* init RF function sums */
sum_rfield = 0;
sum2_rfield = 0;
/* compute a new hashed RF index for each RF layer */
for (j = 0; j < gen_size; j++)
{
sum = 0;
hash_tag = 0;
min_d = (long)1 << ((8 * sizeof(long)) - 2);
/* loop over all dimensions of this RF */
for (i = 0; i < st_size; i++)
{
/* find corner coordinate of excited RF in quantized space */
if (qstate[i] >= base[i])
index = qstate[i] - ((qstate[i] - base[i]) % gen_size);
else
index = (qstate[i] + 1) + ((base[i] - (qstate[i] + 1)) % gen_size) - gen_size;
/* update physical distance to closest side of RF,
and index into RF function table */
test_d = (long)state[i] - (index * (long)qnt[i]);
if (test_d < min_d)
{
min_d = test_d;
rf_index = (RF_TABLE_SIZE * min_d) / ((gen_size * qnt[i]) >> 1);
}
test_d = (((long)gen_size + index) * (long)qnt[i]) - state[i] - 1;
if (test_d < min_d)
{
min_d = test_d;
rf_index = (RF_TABLE_SIZE * min_d) / ((gen_size * qnt[i]) >> 1);
}
/* add table offset for this dimension and wrap around */
index += (449 * i);
index %= 2048;
while (index < 0)
index += 2048;
/* add selected random number to sum */
sum += (long)rndseq[(int)index];
if (!collide)
hash_tag += (int)rndseq2[(int)index];
/* compute displacement of next RF layer in quantized space */
base[i] += disp[i];
}
if (hash_tag == 0) hash_tag = 1;
/* compute psuedo-random index */
indexes[j] = (int)(sum % mem_size);
while (indexes[j] < 0)
indexes[j] += mem_size;
/* now search for hash tag match or open slot */
if (!collide)
{
--indexes[j];
k = 0;
i = (indexes[j] * (rsp_size + 1)) + rsp_size;
do
{
if (++indexes[j] >= mem_size)
{
indexes[j] = 0;
i = rsp_size;
}
else
{
i += rsp_size + 1;
}
} while ((ap[i] != hash_tag) && (ap[i] != 0) && (++k < mem_size));
}
else
{
i = (indexes[j] * (rsp_size + 1)) + rsp_size;
}
/* mark used memory location */
if ((in_learn) && (ap[i] == 0))
ap[i] = hash_tag;
/* update RF function parameters */
if (rf_index >= RF_TABLE_SIZE)
rf_index = RF_TABLE_SIZE - 1;
rfield[j] = rfieldt[rf_index];
sum_rfield += rfieldt[rf_index];
sum2_rfield += ((long)rfieldt[rf_index] * (long)rfieldt[rf_index]);
}
}
static void setup(int cmac_id)
{
ap=ap_a[cmac_id]; /* pointer to cmac storage */
st_size=*ap++; /* size of input state vector */
rsp_size=*ap++; /* dimension of response vector */
gen_size=*ap++; /* generalization parameter */
mem_size=*ap++; /* # of response vectors in memory */
rf_shape=*ap++; /* receptive field code */
collide=*ap++; /* allow hashing collisions ??? */
qnt=ap; /* pointer to quantization vector */
ap+=st_size;
disp=ap; /* pointer to displacement vector */
ap+=st_size;
rfieldt=ap; /* pointer to rf function table */
ap+=RF_TABLE_SIZE; /* pointer to CMAC weights */
}
static void genmap(void)
{
int i, k;
srand(1);
for(k=0;k<2048;k++)
{
rndseq[k]=0;
for(i=0;i<sizeof(int);++i)
rndseq[k]=(rndseq[k]<<8)|(rand()&0xff);
}
for(k=0;k<2048;k++)
{
rndseq2[k] = 0;
for(i=0;i<sizeof(int);++i)
rndseq2[k]=(rndseq2[k]<<8)|(rand()&0xff);
}
}
/***************************************************************************
* Purpose: Initialize lattice displacement vector *
***************************************************************************/
static void init_disp_vector(int dv[],int num_state,int field_shape)
{
int i;
if(field_shape==ALBUS)
{
for(i=0;i<num_state;++i)
dv[i]=1;
}
else
{
for(i=0;i<num_state;++i)
dv[i]=1+(2*i);
}
}
static void init_rfield_table(int rf[],int table_size,int field_shape)
{
int i;
long il;
/* set default constant field magnitude */
for (i=0; i<table_size; ++i) rf[i] = 1;
/* now handle special non-constant cases */
if (field_shape == LINEAR)
{
for (i=0; i<table_size; ++i)
rf[i] = (i + 1);
}
/* now handle special non-constant cases */
if (field_shape == SPLINE)
{
for (i=0; i<table_size; ++i)
{
il = (long)(i + 1);
rf[i] = (int)((((long)-2 * il * il * il) + ((long)3 * il * il * (long)table_size))
/ (long)table_size / (long)table_size);
}
}
}
//分配内存,初始化CMAC的参数//
int allocate_cmac(int num_state,int *qnt_state,int num_resp,
int num_cell,int memory,int field_shape, int collide_flag)
{
int i,j;
int *pntr;
/* initialize data structures on first call to driver */
if (first_call)
{
genmap();
for (i = 0; i <= NUM_CMACS; i++)
ap_a[i] = 0;
first_call = FALSE;
}
/* find an empty id */
for (i = 1; i <= NUM_CMACS; i++) if (ap_a[i] == 0) break;
if (i > NUM_CMACS) return(FALSE); /* return 0 for no more cmacs */
/* allocate CMAC storage */
ap_size[i] = ((memory * (num_resp + 1)) + num_state + num_state + RF_TABLE_SIZE + 6) * sizeof(int);
if (ap_a[i] = (int *)malloc(ap_size[i]))
{
pntr = ap_a[i];
*pntr++ = num_state; /* size of input state vector */
*pntr++ = num_resp; /* dimension of response vector */
*pntr++ = num_cell; /* generalization parameter */
*pntr++ = memory; /* # of response vectors in memory */
*pntr++ = field_shape; /* receptive field code */
*pntr++ = collide_flag; /* hashing collisions flag */
for (j = 0; j < num_state; ++j)
*pntr++ = qnt_state[j]; /* input vector quantization */
init_disp_vector(pntr, num_state, field_shape); /* displacement vector */
pntr += num_state;
init_rfield_table(pntr, RF_TABLE_SIZE, field_shape); /* RF function */
return(i); /* return cmac id number */
}
else
{
return(FALSE);
}
}
int train_cmac(int cmac_id,int *state,int *respns,int beta1,int beta2)
{
int i, j, *weights;
static long sum[MAX_RESPONSE_SIZE], error[MAX_RESPONSE_SIZE];
static long delta1[MAX_RESPONSE_SIZE], delta2;
if ((cmac_id < 1)|(cmac_id > NUM_CMACS)|(ap_a[cmac_id] == 0))
return(FALSE); /* reject bad ID */
in_learn = TRUE;
setup(cmac_id); /* init CMAC parameters */
stoap(state); /* generate indices into ap[][] */
for (j = 0; j < rsp_size; j++)
{
sum[j] = 0;
delta1[j] = 0;
}
delta2 = 0;
/* Process CMACs with rectangular RF field functions */
if ((rf_shape == ALBUS) || (rf_shape == RECTANGULAR))
{
for (i = 0; i < gen_size; i++)
{
/* point to the weight vector for this RF */
weights = &ap[indexes[i] * (rsp_size + 1)];
/* compute the experience sum */
for (j = 0; j < rsp_size; j++)
sum[j] += (long)weights[j];
}
for (j = 0; j < rsp_size; j++)
sum[j] /= gen_size;
/* compute adjustment due to reponse error */
if (beta1 < 32)
{
for (j = 0; j < rsp_size; j++)
{
delta1[j] = ((long)respns[j] - sum[j]);
if (delta1[j] >= 0)
delta1[j] >>= beta1;
else
delta1[j] = -((-delta1[j])>>beta1);
if (delta1[j] == 0)
{
if ((long)respns[j] > sum[j])
{
delta1[j] = 1;
}
else if ((long)respns[j] < sum[j])
{
delta1[j] = -1;
}
}
}
}
/* adjust all weights of all RFs for response */
for (i = 0; i < gen_size; i++)
{
weights = &ap[indexes[i] * (rsp_size + 1)];
for (j = 0; j < rsp_size; j++)
{
/* compute weight normalization adjustment */
if (beta2 < 32)
{
delta2 = (long)(respns[j] - weights[j]);
if (delta2 >= 0)
delta2 = (delta2 >> beta2);
else
delta2 = -((-delta2) >> beta2);
}
/* adjust the weight */
weights[j] += (int)delta1[j] + (int)delta2;
}
}
in_learn = FALSE;
return(TRUE);
}
/* Process CMACs with non-rectangular RF field functions */
/* get old response */
for (i = 0; i < gen_size; i++)
{
/* point to the weight vector for this RF */
weights = &ap[indexes[i] * (rsp_size + 1)];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -