/***************************************************************************** FILE : $Source: /projects/higgs1/SNNS/CVS/SNNS/kernel/sources/dlvq_learn.c,v $ SHORTNAME : SNNS VERSION : 4.2 PURPOSE : Functions of DLVQ NOTES : AUTHOR : Michael Schmalzl DATE : 5.2.93 CHANGED BY : Michael Vogt, Guenter Mamier RCS VERSION : $Revision: 2.12 $ LAST CHANGE : $Date: 1998/03/13 16:23:54 $ Copyright (c) 1990-1995 SNNS Group, IPVR, Univ. Stuttgart, FRG Copyright (c) 1996-1998 SNNS Group, WSI, Univ. Tuebingen, FRG ******************************************************************************/ #include #include #include #include #include #include #ifdef HAVE_VALUES_H #include #endif #include "kr_typ.h" /* Kernel Types and Constants */ #include "kr_const.h" /* Constant Declarators for SNNS-Kernel */ #include "kr_def.h" /* Default Values */ #include "kernel.h" /* kernel function prototypes */ #include "kr_ui.h" #include "kr_mac.h" /* Kernel Macros */ #include "kr_ui.h" #include "cc_mac.h" #include "kr_newpattern.h" #include "cc_glob.h" #include "dlvq_type.h" #include "dlvq_learn.ph" /***************************************************************************** FUNCTION : sortHiddenUnitsByClasses PURPOSE : Sorts the hidden units by its class. NOTES : UPDATE : 5.2.93 ******************************************************************************/ static void sortHiddenUnitsByClasses(int left, int right) { int i,last; struct Unit *temp; if(left >= right ){ return; } temp = FirstHiddenUnitPtr[left]; FirstHiddenUnitPtr[left] = FirstHiddenUnitPtr[(left+right)/2]; FirstHiddenUnitPtr[(left+right)/2] = temp; last = left; for(i=left+1;i<=right;i++){ if(FirstHiddenUnitPtr[i]->bias < FirstHiddenUnitPtr[left]->bias) { temp = FirstHiddenUnitPtr[++last]; FirstHiddenUnitPtr[last]=FirstHiddenUnitPtr[i]; FirstHiddenUnitPtr[i]=temp; } } temp = FirstHiddenUnitPtr[left]; FirstHiddenUnitPtr[left]=FirstHiddenUnitPtr[last]; FirstHiddenUnitPtr[last] = temp; sortHiddenUnitsByClasses(left,last); sortHiddenUnitsByClasses(last+1,right); } /***************************************************************************** FUNCTION : getNoOfClasses PURPOSE : Looks how many different classes exist and checks whether the no. of the first class is zero. NOTES : UPDATE : 5.2.93 ******************************************************************************/ krui_err getNoOfClasses(int startPattern, int endPattern) { int p,patternClass=0,maxPatternClass=0,minPatternClass=0; int *tmpArray,counter,class; int start, end; int pat, sub_pat; Patterns out_pat; KernelErrorCode = kr_initSubPatternOrder(startPattern, endPattern); if (KernelErrorCode != KRERR_NO_ERROR) return KernelErrorCode; start = kr_AbsPosOfFirstSubPat(startPattern); end = kr_AbsPosOfFirstSubPat(endPattern); end += kr_NoOfSubPatPairs(endPattern) - 1; for(p=start; p<=end;p++){ kr_getSubPatternByNo(&pat, &sub_pat, p); out_pat = kr_getSubPatData(pat, sub_pat, OUTPUT, NULL); patternClass = *out_pat; if(patternClass < minPatternClass){ minPatternClass = patternClass; } if(patternClass > maxPatternClass){ maxPatternClass = patternClass; } } if(minPatternClass != 0){ return(DLVQ_ERROR2); /* There exists a class smaller than 0 */ } counter = 0; p = start; tmpArray = (int *)calloc(maxPatternClass+1,sizeof(int)); while((counter != (maxPatternClass+1)) && (p <= end)){ kr_getSubPatternByNo(&pat, &sub_pat, p++); out_pat = kr_getSubPatData(pat, sub_pat, OUTPUT, NULL); class = *out_pat; if(tmpArray[class] == 0){ counter++; tmpArray[class] = 1; } } free(tmpArray); if(counter != (maxPatternClass+1)){ return(DLVQ_ERROR1); /* There are empty classes */ } noOfClasses = maxPatternClass+1; return(KRERR_NO_ERROR); } /***************************************************************************** FUNCTION : allocMixupArray PURPOSE : Allocate the storage of the "mixupArray". NOTES : UPDATE : 5.2.93 ******************************************************************************/ static void allocMixupArray(void) { int i,j; /* free storage */ for(i=0;iweight * linkPtr->weight; } sqrtSum = sqrt(sum); FOR_ALL_LINKS(hiddenUnitPtr,linkPtr){ if(sqrtSum > 0) linkPtr->weight = linkPtr->weight / sqrtSum; else /* Special case */ linkPtr->weight = 0.0; } } /***************************************************************************** FUNCTION : moveVec PURPOSE : Train the vectors. NOTES : UPDATE : 5.2.93 ******************************************************************************/ static void moveVec(struct Unit *correctReferenceVec, float learnParam1, struct Unit *wrongReferenceVec, float learnParam2) { struct Link *linkPtr; FOR_ALL_LINKS(correctReferenceVec,linkPtr){ linkPtr->weight += learnParam1 * (linkPtr->to->act - linkPtr->weight); } normReferenceVec(correctReferenceVec); FOR_ALL_LINKS(wrongReferenceVec,linkPtr){ linkPtr->weight -= learnParam2 * (linkPtr->to->act - linkPtr->weight); } normReferenceVec(wrongReferenceVec); } /***************************************************************************** FUNCTION : PURPOSE : NOTES : UPDATE : 5.2.93 ******************************************************************************/ static void writeVectorToMixupArray(int correctClass, int wrongClass, int patternNo, int sub_pat_no) { Patterns in_pat; double *link=NULL; int i,count; /* calculate startaddress for input pattern array */ in_pat = kr_getSubPatData(patternNo,sub_pat_no,INPUT,&count); link = mixupArray[correctClass][wrongClass].link; for(i=0;i