11 * individual forecaster packages
13 #include "forecasters.h"
18 #define FORECASTER(name,init,params,freer,update,forecaster) \
20 frb = InitForcB(series, \
33 free(derived_forcs); \
35 FreeFBuff(time_stamps); \
39 frb->series = series; \
40 frb->time_stamps = time_stamps; \
41 forcs[l_forcl->count] = frb; \
42 l_forcl->count = l_forcl->count + 1; \
46 #define DERIVED_FORC(name,init,params,freer,update,forecaster) \
48 frb = InitForcB(series, \
59 free((char *)forcs); \
60 free((char *)derived_forcs); \
62 FreeFBuff(time_stamps); \
63 for(i=0; i < l_forcl->count; i++) \
65 FreeForcB(l_forcl->forcs[i]); \
67 free((char *)l_forcl); \
70 frb->series = series; \
71 frb->time_stamps = time_stamps; \
72 derived_forcs[l_forcl->derived_count] = frb; \
73 l_forcl->derived_count = l_forcl->derived_count + 1; \
77 InitForcB(fbuff series,
88 frb = (forcb)malloc(FORCB_SIZE);
97 * get fbuff space for the cumulative error series -- needed
98 * for windowed MSE and MAE predictions
100 frb->se_series = InitFBuff(MAX_MSE_WIN);
102 if(frb->se_series == NULL)
108 frb->ae_series = InitFBuff(MAX_MSE_WIN);
110 if(frb->se_series == NULL)
112 FreeFBuff(frb->se_series);
117 * could be NULL because of derived forecasters
121 frb->state = (*init)(series,time_stamps,params);
124 FreeFBuff(frb->se_series);
125 FreeFBuff(frb->ae_series);
127 fprintf(stderr,"InitForcB: init failed for %s\n",
138 frb->update = update;
139 frb->forecast = forecast;
146 strncpy(frb->name,name,sizeof(frb->name));
149 * point forcb at the series and time stamp buffers
151 frb->series = series;
152 frb->time_stamps = time_stamps;
165 if(frb->state != NULL)
167 frb->free(frb->state);
171 * defensive programming
173 if(frb->se_series != NULL)
175 FreeFBuff(frb->se_series);
177 if(frb->ae_series != NULL)
179 FreeFBuff(frb->ae_series);
187 FreeForcl(char *i_forcl)
192 l_forcl = (forcl)i_forcl;
195 * shared by all forcbs
197 FreeFBuff(l_forcl->forcs[0]->series);
198 FreeFBuff(l_forcl->forcs[0]->time_stamps);
200 for(i=0; i < l_forcl->count; i++)
202 FreeForcB(l_forcl->forcs[i]);
204 for(i=0; i < l_forcl->derived_count; i++)
206 FreeForcB(l_forcl->derived_forcs[i]);
210 * the state is the l_forcl itself -- clear it to free works
213 l_forcl->total_mse->state = NULL;
214 l_forcl->total_mae->state = NULL;
215 FreeForcB(l_forcl->total_mse);
216 FreeForcB(l_forcl->total_mae);
218 free(l_forcl->derived_forcs);
219 free(l_forcl->forcs);
226 * initializes a single fbuff for the data series and another for the
229 * initializes an array of forcb structs, one per forecaster
231 * points each forcb to the series and time stamps
234 InitForcl(int max_forc_count, int buff_size)
238 forcb *derived_forcs;
243 char derived_params[255];
246 * first, get space for series and time stamps
248 series = InitFBuff(buff_size);
251 fprintf(stderr,"InitForcs: couldn't get fbuff for series\n");
256 time_stamps = InitFBuff(buff_size);
257 if(time_stamps == NULL)
260 "InitForcs: couldn't get fbuff for time stamps\n");
267 * now, get forcl list space
269 l_forcl = (forcl)(malloc(FORCL_SIZE));
272 fprintf(stderr,"InitForcs: couldn't malloc %d forcl\n",
276 FreeFBuff(time_stamps);
280 memset((char *)l_forcl,0,FORCL_SIZE);
281 l_forcl->derived_count = 0;
284 * get space for individual forecasters
286 forcs = (forcb *)(malloc(max_forc_count*sizeof(forcb)));
290 fprintf(stderr,"InitForcl: couldn't malloc %d forcb pointers\n",
295 FreeFBuff(time_stamps);
300 * get space for derived forecasters
302 derived_forcs = (forcb *)(malloc(max_forc_count*sizeof(forcb)));
304 if(derived_forcs == NULL)
306 fprintf(stderr,"InitForcl: couldn't malloc %d derived forcb pointers\n",
311 FreeFBuff(time_stamps);
316 l_forcl->forcs = forcs;
317 l_forcl->derived_forcs = derived_forcs;
320 * include the primary forecasters
322 #include "forecasters.c"
326 * now do derived forecaster types
330 * for min MSE, we set the window size to 0. The first
331 * argument is the address of the forc list structure we are building
333 * thread safe? I think not.
335 sprintf(derived_params,
339 DERIVED_FORC("Minimum MSE",
344 LocalWinMSEForecast);
347 * for min MAE, we set the window size to 0. The first
348 * argument is the address of the forc list structure we are building
350 * thread safe? I think not.
352 sprintf(derived_params,
357 DERIVED_FORC("Minimum MAE",
362 LocalWinMAEForecast);
365 * for min windowed MSE, we set the window size to 1. The first
366 * argument is the address of the forc list structure we are building
368 * thread safe? I think not.
370 sprintf(derived_params,
374 DERIVED_FORC("Minimum Window 1 MSE",
379 LocalWinMSEForecast);
381 * for min windowed MSE, we set the window size to 5. The first
382 * argument is the address of the forc list structure we are building
384 * thread safe? I think not.
386 sprintf(derived_params,
390 DERIVED_FORC("Minimum Window 5 MSE",
395 LocalWinMSEForecast);
398 * for min windowed MSE, we set the window size to 10. The first
399 * argument is the address of the forc list structure we are building
401 * thread safe? I think not.
403 sprintf(derived_params,
407 DERIVED_FORC("Minimum Window 10 MSE",
412 LocalWinMSEForecast);
415 * for min windowed MSE, we set the window size to 20. The first
416 * argument is the address of the forc list structure we are building
418 * thread safe? I think not.
420 sprintf(derived_params,
424 DERIVED_FORC("Minimum Window 20 MSE",
429 LocalWinMSEForecast);
431 * for min windowed MSE, we set the window size to 30. The first
432 * argument is the address of the forc list structure we are building
434 * thread safe? I think not.
436 sprintf(derived_params,
440 DERIVED_FORC("Minimum Window 30 MSE",
445 LocalWinMSEForecast);
447 * for min windowed MSE, we set the window size to 50. The first
448 * argument is the address of the forc list structure we are building
450 * thread safe? I think not.
452 sprintf(derived_params,
456 DERIVED_FORC("Minimum Window 50 MSE",
461 LocalWinMSEForecast);
463 * for min windowed MSE, we set the window size to 100. The first
464 * argument is the address of the forc list structure we are building
466 * thread safe? I think not.
468 sprintf(derived_params,
472 DERIVED_FORC("Minimum Window 100 MSE",
477 LocalWinMSEForecast);
480 * for win min MAE, with window size to 1. The first
481 * argument is the address of the forc list structure we are building
483 * thread safe? I think not.
485 sprintf(derived_params,
490 DERIVED_FORC("Minimum Window 1 MAE",
495 LocalWinMAEForecast);
497 * for win min MAE, with window size to 5. The first
498 * argument is the address of the forc list structure we are building
500 * thread safe? I think not.
502 sprintf(derived_params,
507 DERIVED_FORC("Minimum Window 5 MAE",
512 LocalWinMAEForecast);
514 * for win min MAE, with window size to 10. The first
515 * argument is the address of the forc list structure we are building
517 * thread safe? I think not.
519 sprintf(derived_params,
524 DERIVED_FORC("Minimum Window 10 MAE",
529 LocalWinMAEForecast);
531 * for win min MAE, with window size to 20. The first
532 * argument is the address of the forc list structure we are building
534 * thread safe? I think not.
536 sprintf(derived_params,
541 DERIVED_FORC("Minimum Window 20 MAE",
546 LocalWinMAEForecast);
548 * for win min MAE, with window size to 30. The first
549 * argument is the address of the forc list structure we are building
551 * thread safe? I think not.
553 sprintf(derived_params,
558 DERIVED_FORC("Minimum Window 30 MAE",
563 LocalWinMAEForecast);
565 * for win min MAE, with window size to 50. The first
566 * argument is the address of the forc list structure we are building
568 * thread safe? I think not.
570 sprintf(derived_params,
575 DERIVED_FORC("Minimum Window 50 MAE",
580 LocalWinMAEForecast);
582 * for win min MAE, with window size to 100. The first
583 * argument is the address of the forc list structure we are building
585 * thread safe? I think not.
587 sprintf(derived_params,
592 DERIVED_FORC("Minimum Window 100 MAE",
597 LocalWinMAEForecast);
599 * end of derived forecaster init
603 * now init a total MSE forcb for the
607 frb = InitForcB(series,
611 NULL, /* no params */
613 NULL, /* no update */
614 TotalMSEForecast); /* MSE forecast */
620 FreeFBuff(time_stamps);
621 for(i=0; i < l_forcl->count; i++)
623 FreeForcB(l_forcl->forcs[i]);
625 for(i=0; i < l_forcl->derived_count; i++)
627 FreeForcB(l_forcl->derived_forcs[i]);
629 free(l_forcl->derived_forcs);
633 frb->series = series;
634 frb->time_stamps = time_stamps;
639 * total forecasters take forcl as state
641 frb->state = (char *)l_forcl;
642 l_forcl->total_mse = frb;
645 * now init a total MAE forcb for the
649 frb = InitForcB(series,
653 NULL, /* no params */
655 NULL, /* no update */
656 TotalMAEForecast); /* MSE forecast */
662 FreeFBuff(time_stamps);
663 for(i=0; i < l_forcl->count; i++)
665 FreeForcB(l_forcl->forcs[i]);
667 for(i=0; i < l_forcl->derived_count; i++)
669 FreeForcB(l_forcl->derived_forcs[i]);
671 free(l_forcl->derived_forcs);
675 frb->series = series;
676 frb->time_stamps = time_stamps;
681 * total forecasters take forcl as state
683 frb->state = (char *)l_forcl;
684 l_forcl->total_mae = frb;
688 return((char *)l_forcl);
693 UpdateForecasts(char *i_forcl, double ts, double value)
708 l_forcl = (forcl)i_forcl;
713 * get mse forecast for this value and update error
715 ferr = (l_forcl->total_mse)->forecast((l_forcl->total_mse)->state,
720 err = forecast - value;
725 l_forcl->total_mse->ae += err;
726 l_forcl->total_mse->se += err*err;
727 l_forcl->total_mse->count += 1.0;
730 * write out the cumulative total in the
731 * series buffer so that we may do windowed
734 UpdateFBuff(l_forcl->total_mse->se_series,
735 l_forcl->total_mse->se);
736 UpdateFBuff(l_forcl->total_mse->ae_series,
737 l_forcl->total_mse->ae);
740 * get mae forecast for this value and update error
742 ferr = (l_forcl->total_mae)->forecast((l_forcl->total_mae)->state,
746 err = forecast - value;
751 l_forcl->total_mae->ae += err;
752 l_forcl->total_mae->se += err*err;
753 l_forcl->total_mae->count += 1.0;
756 * write out the cumulative total in the
757 * series buffer so that we may do windowed
760 UpdateFBuff(l_forcl->total_mae->se_series,
761 l_forcl->total_mae->se);
762 UpdateFBuff(l_forcl->total_mae->ae_series,
763 l_forcl->total_mae->ae);
769 * update derived forecast error values
771 for(i=0; i < l_forcl->derived_count; i++)
774 * get forecast for this value and update error
777 (l_forcl->derived_forcs[i])->forecast((l_forcl->derived_forcs[i])->state,
784 err = forecast - value;
789 l_forcl->derived_forcs[i]->ae += err;
790 l_forcl->derived_forcs[i]->se += err*err;
791 l_forcl->derived_forcs[i]->count += 1.0;
794 * write out the cumulative total in the
795 * series buffer so that we may do windowed
798 UpdateFBuff(l_forcl->derived_forcs[i]->se_series,
799 l_forcl->derived_forcs[i]->se);
800 UpdateFBuff(l_forcl->derived_forcs[i]->ae_series,
801 l_forcl->derived_forcs[i]->ae);
805 * first, update the error values
807 best_sq_err = DBIG_VAL;
813 for(i=0; i < l_forcl->count; i++)
816 * get forecast for this value and update error
819 (l_forcl->forcs[i])->forecast((l_forcl->forcs[i])->state,&forecast);
825 err = forecast - value;
830 l_forcl->forcs[i]->ae += err;
831 l_forcl->forcs[i]->se += err*err;
832 l_forcl->forcs[i]->count += 1.0;
835 * find the forecast that actually has the min error
837 if((err*err) < best_sq_err)
839 best_sq_err = err*err;
841 best_sq_f = forecast;
850 * write out the cumulative total in the
851 * series buffer so that we may do windowed
854 UpdateFBuff(l_forcl->forcs[i]->se_series,
855 l_forcl->forcs[i]->se);
856 UpdateFBuff(l_forcl->forcs[i]->ae_series,
857 l_forcl->forcs[i]->ae);
861 * record the forecast that actually won
863 if(best_sq_err != DBIG_VAL)
865 l_forcl->total_mse->best_f = best_sq_f;
866 l_forcl->total_mse->best_i = best_sq_i;
867 l_forcl->total_mse->best_err += best_sq_err;
869 l_forcl->total_mae->best_f = best_f;
870 l_forcl->total_mae->best_i = best_i;
871 l_forcl->total_mae->best_err += best_err;
875 * now update the series and time_stamps fbuffs. all forcs point
876 * the same series and time_stamp fbuffs
879 if(l_forcl->count >= 1)
881 UpdateFBuff(l_forcl->forcs[0]->series, value);
882 UpdateFBuff(l_forcl->forcs[0]->time_stamps, ts);
885 for(i=0; i < l_forcl->count; i++)
888 * now update forecast state for the individual forecasters
890 * note that the forecasters need not record the series and
891 * time_stamp points, hence the ts and value parameters
893 (l_forcl->forcs[i])->update((l_forcl->forcs[i])->state,
902 ForcRange(char *i_forcl, double *low, double *high, int *low_i, int *high_i)
906 double min = DBIG_VAL;
907 double max = -1.0 * DBIG_VAL;
911 l_forcl = (forcl)i_forcl;
916 for(i=0; i < l_forcl->count; i++)
918 err = l_forcl->forcs[i]->forecast(l_forcl->forcs[i]->state,
936 if((min == DBIG_VAL) || (max == (-1.0*DBIG_VAL)))
949 PrintForecastSummary(char *i_forcl)
954 l_forcl = (forcl)i_forcl;
959 for(i=0; i < l_forcl->count; i++)
961 fprintf(stdout,"MSE: %3.4f\tMAE: %3.4f\t%s\n",
962 l_forcl->forcs[i]->se/l_forcl->forcs[i]->count,
963 l_forcl->forcs[i]->ae/l_forcl->forcs[i]->count,
964 l_forcl->forcs[i]->name);
968 * secondary forecasters
970 for(i=0; i < l_forcl->derived_count; i++)
972 fprintf(stdout,"MSE: %3.4f\tMAE: %3.4f\t%s\n",
973 l_forcl->derived_forcs[i]->se/l_forcl->derived_forcs[i]->count,
974 l_forcl->derived_forcs[i]->ae/l_forcl->derived_forcs[i]->count,
975 l_forcl->derived_forcs[i]->name);
981 fprintf(stdout,"MSE: %3.4f\tMAE: %3.4f\tTotal MSE\n",
982 l_forcl->total_mse->se / l_forcl->total_mse->count,
983 l_forcl->total_mse->ae / l_forcl->total_mse->count);
984 fprintf(stdout,"MSE: %3.4f\tMAE: %3.4f\tTotal MAE\n",
985 l_forcl->total_mae->se / l_forcl->total_mae->count,
986 l_forcl->total_mae->ae / l_forcl->total_mae->count);
987 fprintf(stdout,"MSE: %3.4f\tMAE: %3.4f\tOptimum\n",
988 l_forcl->total_mse->best_err/l_forcl->total_mse->count,
989 l_forcl->total_mae->best_err/l_forcl->total_mse->count);
995 PrintLifetimeForecastSummary(char *state)
999 flife = (forclife)state;
1001 PrintForecastSummary(flife->forc_list);
1007 * routine put in to support FORECASTAPI_MethodName which doesn't
1008 * take a state record
1011 GetForcNames(char *state, char *methodNames[], int max_size, int *out_size)
1018 for(i=0; i < max_size; i++)
1023 methodNames[i] = s->forcs[i]->name;
1032 InitForcLife(int max_forc_count, int buff_size, double lifetime)
1038 * get a forc list for the series
1040 l_forcl = InitForcl(max_forc_count, buff_size);
1043 fprintf(stderr,"InitForcLife: no space for forc list\n");
1049 * now, get space for the lifetime forecasting structure
1051 flife = (forclife)malloc(FORCLIFE_SIZE);
1055 fprintf(stderr,"InitForcLife: no space for forclife struct\n");
1061 flife->lifetime = lifetime;
1062 flife->epoch_end = 0.0;
1065 flife->forc_list = l_forcl;
1067 return((char *)flife);
1071 FreeForcLife(char *state)
1075 flife = (forclife)state;
1077 FreeForcl(flife->forc_list);
1084 UpdateForcLife(char *state, double ts, double value)
1089 flife = (forclife)state;
1092 * if we are initializing
1094 if(flife->epoch_end == 0.0)
1096 flife->epoch_end = ts + flife->lifetime;
1099 if(ts < flife->epoch_end)
1101 flife->total += value;
1102 flife->count += 1.0;
1106 if(flife->count == 0.0)
1109 avg = flife->total / flife->count;
1110 UpdateForecasts((char *)flife->forc_list,
1115 flife->epoch_end = ts+flife->lifetime;
1122 LifetimeValue(char *state)
1128 flife = (forclife)state;
1129 l_forcl = (forcl)flife->forc_list;
1132 F_VAL(l_forcl->forcs[0]->series,F_FIRST(l_forcl->forcs[0]->series));
1138 LifetimeTimestamp(char *state)
1144 flife = (forclife)state;
1145 l_forcl = (forcl)flife->forc_list;
1148 F_VAL(l_forcl->forcs[0]->time_stamps,
1149 F_FIRST(l_forcl->forcs[0]->time_stamps));