home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / c / GAPLib.lha / GAPLib / utility / report.c next >
Encoding:
C/C++ Source or Header  |  1999-05-21  |  6.8 KB  |  334 lines

  1. /*
  2.  * Report file generation utility code.
  3.  * See report.doc for more info.
  4.  *
  5.  * (C)1998-1999 Peter Bengtsson
  6.  *
  7.  * 21/5-1999:
  8.  *    Added indexed mode.
  9.  *
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <stdarg.h>
  16. #include <sys/stat.h>
  17. #include <errno.h>
  18. #include <GAP.h>
  19.  
  20. #include "report.h"
  21.  
  22. #define    MAX_INDEX    2048    /* Generate at most 2048 indices. */
  23.  
  24. static const char * const exts[REPFILES] = {
  25.     "avg",
  26.     "med",
  27.     "typ",
  28.     "max",
  29.     "min",
  30.     "dev"
  31. };
  32.  
  33. static const char * const descs[REPFILES] = {
  34.     "Average",
  35.     "Median",
  36.     "TypeCount",
  37.     "Max",
  38.     "Min",
  39.     "StdDev"
  40. };
  41.  
  42. struct Report *MakeReport(char *,struct TagItem *);
  43. void DoReport(struct Report *,struct Population *,unsigned int);
  44. void EndReport(struct Report *rs);
  45.  
  46. struct Report *MakeReport(char *basename,struct TagItem *TagList)
  47. {
  48. struct Report *rs;
  49. char    *buf=NULL;
  50. int i,n,t;
  51. int Index=MAX_INDEX;
  52. Tag    tag=TAG_DONE;
  53.  
  54. rs = malloc(sizeof(struct Report));
  55.  
  56. rs->flags=0;
  57. rs->gencount=0;
  58.  
  59. for(i=0;i!=REPFILES;i++) {
  60.     rs->vbuffer[i]=NULL;
  61.     rs->cbuffer[i] = 0;
  62. }
  63.  
  64. i=0;
  65.  
  66. if(rs!=0) {
  67.  
  68.     if(TagList!=NULL) {
  69.         tag = TagList[0].ti_Tag;
  70.     }
  71.  
  72.     while(tag!=TAG_DONE) {    /* Handling of TAG_MORE & TAG_IGNORE is still missing. */
  73.  
  74.         switch(tag) {
  75.  
  76.         case    REP_Generations:
  77.             rs->gencount = TagList[i].ti_Data;
  78.         break;
  79.  
  80.         case    REP_Multipass:
  81.             rs->flags &= ~RFLG_MPASS;
  82.             if(TagList[i].ti_Data!=FALSE) {
  83.                 rs->flags |= RFLG_MPASS;
  84.             }
  85.         break;
  86.  
  87.         case    REP_Indexed:
  88.             rs->flags &= ~RFLG_INDXD;
  89.             if(TagList[i].ti_Data!=FALSE) {
  90.                 rs->flags |= RFLG_INDXD;
  91.             }
  92.         break;
  93.  
  94.         default:
  95.             fprintf(stderr,"MakeReport: Unrecognized tag 0x%08lx.\n",tag);
  96.         }
  97.  
  98.         tag = TagList[++i].ti_Tag;
  99.     }
  100.  
  101.     if((rs->flags&RFLG_MPASS) && rs->gencount==0) {
  102.         fprintf(stderr,"MakeReport: Multipass mode selected but number of generations undeclared.\nDisabling multipass mode.\n");
  103.         rs->flags &= ~RFLG_MPASS;
  104.     }
  105.  
  106.     if(basename!=NULL) {
  107.         buf = malloc((strlen(basename)+8)*sizeof(char));
  108.         rs->basename = malloc((strlen(basename)+1)*sizeof(char));
  109.         strcpy(rs->basename,basename);
  110.  
  111.         if(rs!=NULL && rs->basename!=NULL && buf!=NULL) {
  112.             if(rs->flags&RFLG_INDXD) {    /* Determine index of file. */
  113.                 struct stat State;
  114.                 i=-1;
  115.                 while(++i<MAX_INDEX) {
  116.                     t=1;
  117.                     for(n=0;n!=REPFILES;n++) {
  118.                         sprintf(buf,"%s%d.%s",basename,i,exts[n]);
  119.                         if((t=stat(buf,&State))==0) {
  120.                             break;
  121.                         }
  122.                     }
  123.                     if(t!=0) {
  124.                         if(errno==ENOENT) {
  125.                             Index=i;
  126.                             break;
  127.                         }
  128.                     }
  129.                 }
  130.             }
  131.  
  132.             rs->index = Index;
  133.  
  134.             for(i=0;i!=REPFILES;i++) {
  135.                 if(rs->flags&RFLG_INDXD) {
  136.                     sprintf(buf,"%s%d.%s",basename,Index,exts[i]);
  137.                 } else {
  138.                     sprintf(buf,"%s.%s",basename,exts[i]);
  139.                 }
  140.  
  141.                 if((rs->files[i]=fopen(buf,"wb"))==NULL) {
  142.                     while(--i>=0) {
  143.                         fclose(rs->files[i]);
  144.                     }
  145.                     free(rs->basename);
  146.                     free(rs);
  147.                     rs = NULL;
  148.                     fprintf(stderr,"MakeReport: Error opening files for writing.\n");
  149.                 }
  150.                 rs->used[i]=0;
  151.                 fprintf(rs->files[i],"# Generation, %s\n",descs[i]);
  152.             }
  153.         } else {
  154.             if(rs!=NULL) {
  155.                 if(rs->basename!=NULL) {
  156.                     free(rs->basename);
  157.                 }
  158.                 free(rs);
  159.                 rs = NULL;
  160.             }
  161.             fprintf(stderr,"MakeReport: No free store (malloc() failed).\n");
  162.         }
  163.     } else {
  164.         fprintf(stderr,"MakeReport: NULL basename.\n");
  165.     }
  166.  
  167.     if(buf!=NULL) {
  168.         free(buf);
  169.     }
  170.  
  171. }
  172.  
  173. return(rs);
  174. }
  175.  
  176. void EndReport(struct Report *rs)
  177. {
  178. int i,n;
  179. char *buf=NULL;
  180.  
  181. if(rs!=NULL) {
  182.     if(rs->flags&RFLG_MPASS) {
  183.         for(i=0;i!=REPFILES;i++) {
  184.             if(rs->used[i]!=0) {
  185.                 for(n=0;n!=rs->gencount;n++) {
  186.                     fprintf(rs->files[i],"%d %f\n",n+1,rs->vbuffer[i][n]/((double)rs->cbuffer[i]));
  187.                 }
  188.             }
  189.         }
  190.     }
  191.     buf=malloc((strlen(rs->basename)+8)*sizeof(char));
  192.     for(i=0;i!=REPFILES;i++) {
  193.         fclose(rs->files[i]);    /* fclose does an fflush. */
  194.         if(rs->used[i]==0 && buf!=NULL) {
  195.             if(rs->flags&RFLG_INDXD) {
  196.                 sprintf(buf,"%s%d.%s",rs->basename,rs->index,exts[i]);
  197.             } else {
  198.                 sprintf(buf,"%s.%s",rs->basename,exts[i]);
  199.             }
  200.  
  201.             remove(buf);
  202.         }
  203.     }
  204.  
  205.     if(rs->flags&RFLG_VBUF) {
  206.         for(i=0;i!=REPFILES;i++) {
  207.             if(rs->vbuffer[i]!=NULL) {
  208.                 free(rs->vbuffer[i]);
  209.             }
  210.         }
  211.     }
  212.  
  213.     free(rs->basename);
  214.     free(rs);
  215. }
  216.  
  217. if(buf!=NULL) {
  218.     free(buf);
  219. } else {
  220.     fprintf(stderr,"EndReport: No free store, continuing.\n");
  221. }
  222.  
  223. }
  224.  
  225. void DoReport(struct Report *rs,struct Population *Pop,unsigned int flags)
  226. {
  227. int i,n,t;
  228. struct Popstat *stat;
  229.  
  230. if(rs!=NULL && Pop!=NULL && flags!=0) {
  231.     stat = &Pop->Stat;
  232.     for(i=0;i!=REPFILES;i++) {
  233.         n = flags&(1<<i);
  234.         if(n!=0) {
  235.             rs->used[i]=1;
  236.             if(rs->flags&RFLG_MPASS) {
  237.                 if(stat->Generation==1) {
  238.                     rs->cbuffer[i]++;
  239.                 }
  240.                 if(stat->Generation>rs->gencount) {
  241.                     fprintf(stderr,"DoReport: Generation overflow.\n");
  242.                 } else {
  243.                     if(rs->vbuffer[i]==NULL) {
  244.                         if(rs->flags&RFLG_NOMEM) {
  245.                             break;
  246.                         }
  247.                         rs->flags |= RFLG_VBUF;
  248.                         rs->vbuffer[i] = malloc(rs->gencount*sizeof(double));
  249.                         if(rs->vbuffer[i]==NULL) {
  250.                             rs->flags |= RFLG_NOMEM;
  251.                             fprintf(stderr,"DoReport: No free store for multipass buffer.\n(Failed to allocate %ld bytes.)\n",rs->gencount*sizeof(double));
  252.                             break;
  253.                         } else {
  254.                             for(t=0;t!=rs->gencount;t++) {
  255.                                 rs->vbuffer[i][t] = 0.0;
  256.                             }
  257.                         }
  258.                     }
  259.                     switch(n) {
  260.                     case    AVERAGE:
  261.                         rs->vbuffer[i][stat->Generation-1] += stat->AverageFitness;
  262.                     break;
  263.                     case    MEDIAN:
  264.                         rs->vbuffer[i][stat->Generation-1] += stat->MedianFitness;
  265.                     break;
  266.                     case    TYPECOUNT:
  267.                         rs->vbuffer[i][stat->Generation-1] += (double) stat->TypeCount;
  268.                     break;
  269.                     case    MAX:
  270.                         rs->vbuffer[i][stat->Generation-1] += stat->MaxFitness;
  271.                     break;
  272.                     case    MIN:
  273.                         rs->vbuffer[i][stat->Generation-1] += stat->MinFitness;
  274.                     break;
  275.                     case    STDDEV:
  276.                         rs->vbuffer[i][stat->Generation-1] += stat->StdDeviation;
  277.                     break;
  278.                     }
  279.                 }
  280.             } else {
  281.                 switch(n) {
  282.                 case    AVERAGE:
  283.                     fprintf(rs->files[i],"%ld %f\n",stat->Generation,stat->AverageFitness);
  284.                 break;
  285.                 case    MEDIAN:
  286.                     fprintf(rs->files[i],"%ld %f\n",stat->Generation,stat->MedianFitness);
  287.                 break;
  288.                 case    TYPECOUNT:
  289.                     fprintf(rs->files[i],"%ld %ld\n",stat->Generation,stat->TypeCount);
  290.                 break;
  291.                 case    MAX:
  292.                     fprintf(rs->files[i],"%ld %f\n",stat->Generation,stat->MaxFitness);
  293.                 break;
  294.                 case    MIN:
  295.                     fprintf(rs->files[i],"%ld %f\n",stat->Generation,stat->MinFitness);
  296.                 break;
  297.                 case    STDDEV:
  298.                     fprintf(rs->files[i],"%ld %f\n",stat->Generation,stat->StdDeviation);
  299.                 break;
  300.                 }
  301.             }
  302.         }
  303.     }
  304. }
  305.  
  306. }
  307.  
  308. struct Report *MakeReportT(char *basename,...)
  309. {
  310. va_list ap;
  311. int i=0;
  312. struct TagItem TagList[64]; /* Assumed big enough */
  313.  
  314. va_start(ap,basename);
  315.  
  316. while((TagList[i].ti_Tag = va_arg(ap,Tag)),TagList[i].ti_Tag != TAG_DONE && TagList[i].ti_Tag != TAG_MORE) {
  317.     TagList[i].ti_Data = va_arg(ap,IPTR);
  318.     i++;
  319. }
  320.  
  321. if(TagList[i].ti_Tag == TAG_MORE) {
  322.     TagList[i].ti_Data = va_arg(ap,IPTR);
  323.     if(TagList[i].ti_Data == 0) {
  324.         fprintf(stderr,"MakeReportT: Illegal NULL value for TAG_MORE.\n");
  325.         TagList[i].ti_Tag = TAG_DONE;
  326.     }
  327. }
  328.  
  329. va_end(ap);
  330.  
  331. return (MakeReport(basename,TagList));
  332. }
  333.  
  334.