Iterative accumulative topographical global optimization algorithm (IATGO).
701 {
702 FILE *fp=stdout;
703 int verbose=0;
if(status!=NULL) {verbose=status->
verbose; fp=status->
fp;}
704 if(verbose>1) {
705 fprintf(fp, "%s(NLOPT, %d, %u, %g, status)\n", __func__, doLocal, maxIterNr, neighFract);
706 fflush(fp);
707 }
708 if(nlo==NULL ) {
711 }
715 }
716
718
719 if(verbose>4) {
720 fprintf(fp, "\nInitial limits and tolerances:\n");
721 for(unsigned int i=0; i<dim; i++)
722 fprintf(fp,
"\t%g\t%g\t%e\n", nlo->
xlower[i], nlo->
xupper[i], nlo->
xtol[i]);
723 }
724
725
727 if(verbose>2 && fixedParNr>0) fprintf(fp, "fixedParNr := %d\n", fixedParNr);
728 unsigned int fittedParNr=nlo->
totalNr-fixedParNr;
729 if(verbose>2) {fprintf(fp, "fittedParNr := %d\n", fittedParNr); fflush(fp);}
730 if(fittedParNr<1) {
733 }
734
735
736 for(unsigned int i=0; i<dim; i++) {
738 if(!(nlo->
xtol[i]>0.0)) {
739 if(verbose>0) {fprintf(stderr, "Error: invalid xtol[].\n"); fflush(stderr);}
742 }
743 }
744
745
746 if(neighFract<0.04) neighFract=0.04; else if(neighFract>0.97) neighFract=0.97;
747 unsigned int sampleNr=50*fittedParNr/neighFract;
748 if(maxIterNr==0) maxIterNr=5+2*fittedParNr;
749 unsigned int neighNr=neighFract*sampleNr;
750 if(verbose>2) {
751 fprintf(fp, "sampleNr := %u\n", sampleNr);
752 fprintf(fp, "neighFract := %g\n", neighFract);
753 fprintf(fp, "neighNr := %u\n", neighNr);
754 fprintf(fp, "maxIterNr := %u\n", maxIterNr);
755 fflush(stdout);
756 }
757
758
759
760
761
762 if(verbose>3) {fprintf(fp, "Making initial random samples\n"); fflush(fp);}
763
764
767 nlo->
plist=(
double*)malloc(sampleNr*(dim+1)*
sizeof(
double));
768 if(nlo->
plist==NULL) {
771 }
772
773
774 {
775 unsigned int badNr=0;
776
777 for(unsigned int si=0; si<sampleNr; si++) {
781 }
784 if(!isfinite(nlo->
plist[si*(dim+1)+dim])) badNr++;
785 }
786 if(verbose>3 && badNr>0) fprintf(fp, "Number of bad points: %d\n", badNr);
787
788 if((sampleNr-badNr)<10) {
789 if(verbose>0) {
790 fprintf(stderr, "Error: invalid values inside parameter range.\n"); fflush(stderr);}
793 }
794
795 if(badNr>0) {
796 badNr=0;
797 for(
unsigned int si=0; si<sampleNr; si++)
if(!isfinite(nlo->
plist[si*(dim+1)+dim])) {
800
801 if(!isfinite(nlo->
plist[si*(dim+1)+dim])) badNr++;
802 }
803 if(verbose>4 && badNr>0) fprintf(fp, "Number of bad points after retry: %d\n", badNr);
804 }
805 }
806
807
808 int initGuessAvailable=1;
809 double initGuessCost=nan("");
810 for(unsigned int i=0; i<dim; i++) {
811 if(isnan(nlo->
xfull[i])) {initGuessAvailable=0;
break;}
812 if(nlo->
xfull[i]<nlo->
xlower[i]) {initGuessAvailable=0;
break;}
813 if(nlo->
xfull[i]>nlo->
xupper[i]) {initGuessAvailable=0;
break;}
814 }
815 if(initGuessAvailable) {
817 if(isfinite(initGuessCost)) {
820 } else {
821 initGuessAvailable=0;
822 }
823 }
824 if(verbose>2) {
825 if(initGuessAvailable) fprintf(fp, "valid initial guess with cost=%g\n", initGuessCost);
826 else fprintf(fp, "no valid initial guess provided.\n");
827 }
828
829
830
831
832
833 if(verbose>2) {fprintf(fp, "\nStarting TGO iterations\n"); fflush(fp);}
834 unsigned int iterNr=0, stopCounter=0;
835 double prevBest=nan("");
836 while(iterNr<maxIterNr && nlo->funCalls<nlo->maxFunCalls) {
837 iterNr++;
838 unsigned int sampleNr=nlo->
funCalls;
839 if(verbose>3) {fprintf(fp, "\nIteration %d with %d samples\n", iterNr, sampleNr); fflush(fp);}
840
841
844
845
846 if(verbose>15) {fprintf(fp,
"Points so far:\n");
nloptPrintP(nlo, 0, fp);}
847 else if(verbose>6) {fprintf(fp,
"Best points so far:\n");
nloptPrintP(nlo, 10, fp);}
848 else if(verbose>4) {
849 fprintf(fp, "best point so far:");
850 for(
unsigned int i=0; i<dim; i++) fprintf(fp,
" %e", nlo->
plist[i]);
851 fprintf(fp,
" => %e\n", nlo->
plist[dim]); fflush(fp);
852 }
853
854
855 if(verbose>4 && !isnan(prevBest))
856 fprintf(fp,
"dif_to_prev_point := %e\n", prevBest-nlo->
plist[dim]);
857 if(!isnan(prevBest) && (prevBest-nlo->
plist[dim])<1.0E-20) {
858 if(verbose>4) fprintf(fp, "Best point did not improve.\n");
860 unsigned int i=0;
861 for(i=0; i<dim; i++)
if(fabs(nlo->
xdelta[i])>nlo->
xtol[i])
break;
862 if(i==dim) {
863 if(verbose>2) fprintf(fp, "Small SD of best points.\n");
864 stopCounter++;
865 } else stopCounter=0;
866 }
867 } else stopCounter=0;
868 prevBest=nlo->
plist[dim];
869
870
871 if(verbose>4) fprintf(fp, "stopCounter := %d\n", stopCounter);
872 if(stopCounter>2) {
873 if(verbose>2) fprintf(fp, "\n Required tolerance reached.\n");
874 break;
875 }
876
877
878
879
880
881 unsigned int tmlist[sampleNr];
882 for(unsigned int i=0; i<sampleNr; i++) tmlist[i]=0;
883
884 unsigned int topoNr=0;
885 if(verbose>3) {fprintf(fp, "neighNr := %d\n", neighNr); fflush(fp);}
886
887
888
889 for(unsigned int si=0; si<sampleNr-neighNr; si++) if(tmlist[si]==0) {
890
891
892 if(!isfinite(nlo->
plist[si*(dim+1)+dim]))
continue;
893
894
895 double sdist[sampleNr];
896 for(unsigned int sj=0; sj<sampleNr; sj++) {
897 if(si==sj || !isfinite(nlo->
plist[sj*(dim+1)+dim])) {
898 sdist[sj]=nan(""); continue;}
899 sdist[sj]=0.0;
900 for(unsigned int k=0; k<dim; k++) {
901 if(!(nlo->
xtol[k]>0.0))
continue;
902 double d=(nlo->
plist[si*(dim+1)+k]-nlo->
plist[sj*(dim+1)+k])/nlo->
xtol[k];
903 sdist[sj]+=d*d;
904 }
905
906
907 }
908 double sdist2[sampleNr];
909 for(unsigned int sj=0; sj<sampleNr; sj++) sdist2[sj]=sdist[sj];
910
911
912 unsigned int nn=0; double prev_mind=nan("");
913 while(1) {
914
915 unsigned int mini=0;
916 double mind=nan("");
917 for(unsigned int sj=0; sj<sampleNr; sj++) {
918 if(!isfinite(mind) || mind>sdist[sj]) {mind=sdist[sj]; mini=sj;}
919 }
920 if(!isfinite(mind)) break;
921 sdist[mini]=nan("");
922 if(verbose>100) fprintf(fp, " min_distance[%u] := %g , with fval := %g\n",
923 1+nn, mind, nlo->
plist[mini*(dim+1)+dim]);
924
925 if(nlo->
plist[mini*(dim+1)+dim] < nlo->
plist[si*(dim+1)+dim])
break;
926
927 nn++; tmlist[mini]=1+si;
928
929
930
931 if(isnan(prev_mind)) prev_mind=mind;
932 if(nn>=neighNr && mind>1.0 && mind>prev_mind) break;
933 prev_mind=mind;
934 }
935
936
937 if(nn<neighNr) {
938
939 for(unsigned int ni=0; ni<sampleNr; ni++) if(tmlist[ni]==1+si) tmlist[ni]=0;
940 continue;
941 }
942
943 tmlist[si]=1+si;
944 topoNr++;
945
946 if(verbose>5) {
947 fprintf(fp, "TM point %d\t", 1+si);
948 for(
unsigned int i=0; i<dim; i++) fprintf(fp,
"%e ", nlo->
plist[si*(dim+1)+i]);
949 fprintf(fp,
"=> %e\n", nlo->
plist[si*(dim+1)+dim]);
950 if(verbose>14) {
951 fprintf(fp, "and its %u neighbours:\n", nn);
952 for(unsigned int sj=0; sj<sampleNr; sj++) if(sj!=si && tmlist[sj]==1+si) {
953 for(
unsigned int i=0; i<dim; i++) fprintf(fp,
"%e ", nlo->
plist[sj*(dim+1)+i]);
954 fprintf(fp,
"=> %e\t(%g)\n", nlo->
plist[sj*(dim+1)+dim], sdist2[sj]);
955 }
956 }
957 fflush(fp);
958 }
959 }
960 if(verbose>3) {fprintf(fp, "topographic minima: %d\n", topoNr); fflush(fp);}
961 if(topoNr==0) {
962 if(verbose>0) {fprintf(stderr, "Error: no topographical minima found\n"); fflush(stderr);}
965 }
966
967
968
969
970 for(unsigned int si=0; si<sampleNr; si++) if(tmlist[si]==1+si) {
971 if(verbose>5) {fprintf(fp, "LO for TM point %d\n", 1+si); fflush(fp);}
972 if(verbose>6) {
973 fprintf(fp, "TM point %d before LO:\n", 1+si);
974 for(
unsigned int i=0; i<dim; i++) fprintf(fp,
" %e", nlo->
plist[si*(dim+1)+i]);
975 fprintf(fp,
" => %e\n", nlo->
plist[si*(dim+1)+dim]); fflush(fp);
976 }
977
978 double meanp[dim], sdp[dim]; unsigned int nn=0;
979 for(unsigned int i=0; i<dim; i++) {
981 double x[sampleNr];
982 nn=0;
983 for(unsigned int sj=0; sj<sampleNr; sj++)
984 if(tmlist[sj]==1+si) x[nn++]=nlo->
plist[sj*(dim+1)+i];
986 } else {
987 meanp[i]=nlo->
xlower[i]; sdp[i]=0.0;
988 }
989 }
990 if(verbose>7) {
991 fprintf(fp, "TM point (n=%u) mean and SD:\n", nn);
992 for(unsigned int i=0; i<dim; i++) fprintf(fp, "\t%g\t%g\n", meanp[i], sdp[i]);
993 fflush(fp);
994 }
995
996 for(
unsigned int i=0; i<dim; i++)
if(nlo->
xupper[i]>nlo->
xlower[i]) {
998 }
999 if(doLocal==1) {
1004 if(verbose>1) {fprintf(fp,
" LO failed: %s\n",
errorMsg(ret)); fflush(fp);}
1005 } else {
1006 if(verbose>6) {
1007 fprintf(fp, "Point after LO:");
1008 for(
unsigned int i=0; i<dim; i++) fprintf(fp,
" %e ", nlo->
xfull[i]);
1009 fprintf(fp,
" => %e\n", nlo->
funval); fflush(fp);
1010 }
1011 }
1012 } else {
1013 unsigned int bi=0; double bval=nan("");
1014 for(unsigned int ni=0; ni<neighNr; ni++) {
1015 double p[dim];
1018 if(isnan(bval) || bval>fval) {bval=fval; bi=nlo->
funCalls;}
1020 }
1021 if(verbose>6) {
1022 fprintf(fp, "Best TM point %d after LO:\n", 1+si);
1023 for(
unsigned int i=0; i<dim; i++) fprintf(fp,
" %e", nlo->
plist[bi*(dim+1)+i]);
1024 fprintf(fp,
" => %e\n", nlo->
plist[bi*(dim+1)+dim]); fflush(fp);
1025 }
1026 }
1027 }
1028
1029 }
1030
1031
1032 if(verbose>1) {
1033 if(iterNr>=maxIterNr)
1034 fprintf(fp, "\n Exceeded the maximum number for loops.\n");
1036 fprintf(fp, "\n Exceeded the maximum number for function calls.\n");
1037 fflush(fp);
1038 }
1039
1040
1043
1044 for(
unsigned int i=0; i<dim; i++) nlo->
xfull[i]=nlo->
plist[i];
1046
1047
1050}
void doubleCopy(double *t, double *s, const unsigned int n)
double drandExponential(double mean)
Get pseudo-random number with exponential distribution.
int statMeanSD(double *data, unsigned int n, double *mean, double *sd, unsigned int *vn)
unsigned int nloptLimitFixedNr(NLOPT *d)
int nloptMeanP(NLOPT *nlo, unsigned int nr, double *meanp, double *sdp)
void nloptPrintP(NLOPT *nlo, unsigned int nr, FILE *fp)
int nloptAddP(NLOPT *nlo, double *p, double funval)
int nloptSortP(NLOPT *nlo)
int nloptRandomPoint(double *p, double *low, double *up, unsigned int n, MERTWI *mt)
int nloptGaussianPoint(double *p, double *mean, double *sd, double *low, double *up, unsigned int n, MERTWI *mt)
int nloptSimplex(NLOPT *nlo, unsigned int maxIter, TPCSTATUS *status)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
double(* _fun)(int, double *, void *)
int verbose
Verbose level, used by statusPrint() etc.
FILE * fp
File pointer for writing log information during development and testing.
@ TPCERROR_BAD_FIT
Fitting not successful.
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_NO_DATA
File contains no data.