/* $Id: vfsr.h,v 7.3 1993/02/04 18:33:51 ingber Exp ingber $ */ /* vfsr.h for Very Fast Simulated Reannealing */ #include #include #include #include /* misc defs on most machines */ /* INCLUDE THIS FILE IF YOUR C COMPILER ONLY ACCEPTS IDENTIFIERS OF LESS THAN 32 CHARACTERS. */ /* #include longname.h */ #define TRUE 1 #define FALSE 0 #define INTEGER_TYPE 1 #define REAL_TYPE 0 #define ZERO ((double) 0.0) #define ONE ((double) 1.0) #define TWO ((double) 2.0) #define TEN ((double) 10.0) #define HALF ((double) 0.5) #define NORMAL_EXIT 0 #define P_TEMP_TOO_SMALL 1 #define C_TEMP_TOO_SMALL 2 #define COST_REPEATING 3 #define TOO_MANY_INVALID_STATES 4 /* DEFAULT PARAMETERS SETTINGS */ /* Machine Options */ #ifndef HAVE_ANSI #define HAVE_ANSI TRUE #endif #ifndef IO_PROTOTYPES #define IO_PROTOTYPES TRUE #endif #ifndef TIME_CALC #define TIME_CALC TRUE #endif #if TIME_CALC #include #include #endif #ifndef INT_LONG #define INT_LONG TRUE #endif #if INT_LONG #define LONG_INT long int #else #define LONG_INT int #endif /* You can define SMALL_FLOAT to better correlate to your machine's precision, i.e., as used in vfsr */ #ifndef SMALL_FLOAT #define SMALL_FLOAT 1.0E-18 #endif /* You can define your machine's maximum and minimum reals here */ #ifndef MIN_FLOAT #define MIN_FLOAT (-1.0/SMALL_FLOAT) #endif /* #define MAX_FLOAT MAX_REAL */ #ifndef MAX_FLOAT #define MAX_FLOAT (1.0/SMALL_FLOAT) #endif /* Printing Options */ #ifndef VFSR_PRINT #define VFSR_PRINT TRUE #endif #ifndef VFSR_OUT #define VFSR_OUT "vfsr_out" #endif /* Program Options */ #ifndef ADAPTIVE_OPTIONS #define ADAPTIVE_OPTIONS FALSE #endif #ifndef OPTIONS_FILE #define OPTIONS_FILE FALSE #endif #if ADAPTIVE_OPTIONS typedef struct { double g_COST_PRECISION; int g_USER_INITIAL_PARAMETERS; double g_ACCEPTED_TO_GENERATED_RATIO; int g_LIMIT_ACCEPTANCES; double g_TEMPERATURE_RATIO_SCALE; double g_TEMPERATURE_ANNEAL_SCALE; double g_COST_PARAMETER_SCALE; int g_TESTING_FREQUENCY_MODULUS; int g_MAXIMUM_REANNEAL_INDEX; double g_REANNEAL_RESCALE; double g_INITIAL_PARAMETER_TEMPERATURE; int g_USER_INITIAL_PARAMETERS_TEMPS; int g_USER_INITIAL_COST_TEMP; int g_NUMBER_COST_SAMPLES; int g_MAXIMUM_COST_REPEAT; double g_DELTA_X; int g_INCLUDE_INTEGER_PARAMETERS; int g_ACTIVATE_REANNEAL; int g_LIMIT_INVALID_GENERATED_STATES; } DEFINES; DEFINES *OPTIONS; #else /* ADAPTIVE_OPTIONS */ typedef int DEFINES; DEFINES *OPTIONS; #ifndef COST_PRECISION /* precision at MAXIMUM_COST_REPEAT */ #define COST_PRECISION SMALL_FLOAT #endif #ifndef USER_INITIAL_PARAMETERS #define USER_INITIAL_PARAMETERS FALSE #endif #ifndef ACCEPTED_TO_GENERATED_RATIO /* determines when to test */ #define ACCEPTED_TO_GENERATED_RATIO 1.0E-6 #endif #ifndef LIMIT_ACCEPTANCES /* max number of acceptances */ #define LIMIT_ACCEPTANCES 10000 #endif #ifndef TEMPERATURE_RATIO_SCALE #define TEMPERATURE_RATIO_SCALE 1.0E-5 #endif #ifndef TEMPERATURE_ANNEAL_SCALE #define TEMPERATURE_ANNEAL_SCALE 100.0 #endif #ifndef COST_PARAMETER_SCALE #define COST_PARAMETER_SCALE 1.0 #endif #ifndef TESTING_FREQUENCY_MODULUS #define TESTING_FREQUENCY_MODULUS 100 #endif #ifndef MAXIMUM_REANNEAL_INDEX #define MAXIMUM_REANNEAL_INDEX 100000000 #endif #ifndef REANNEAL_RESCALE #define REANNEAL_RESCALE 10.0 #endif #ifndef INITIAL_PARAMETER_TEMPERATURE #define INITIAL_PARAMETER_TEMPERATURE 1.0 #endif #ifndef USER_INITIAL_PARAMETERS_TEMPS /* "hook" into *tangents */ #define USER_INITIAL_PARAMETERS_TEMPS FALSE #endif #ifndef USER_INITIAL_COST_TEMP /* "hook" into curvature[0] */ #define USER_INITIAL_COST_TEMP FALSE #endif #ifndef NUMBER_COST_SAMPLES #define NUMBER_COST_SAMPLES 5 #endif #ifndef MAXIMUM_COST_REPEAT #define MAXIMUM_COST_REPEAT 5 #endif /* delta of derivatives in cost_derivatives */ #ifndef DELTA_X #define DELTA_X 0.001 #endif #ifndef INCLUDE_INTEGER_PARAMETERS /* in derivative calculations */ #define INCLUDE_INTEGER_PARAMETERS FALSE #endif #ifndef ACTIVATE_REANNEAL #define ACTIVATE_REANNEAL TRUE #endif #ifndef LIMIT_INVALID_GENERATED_STATES #define LIMIT_INVALID_GENERATED_STATES 1000 #endif #endif /* ADAPTIVE_OPTIONS */ /* essential MACROS */ /* VFOR is a simple macro to iterate on each parameter index. */ #define VFOR(index_v) \ for (index_v = 0; index_v < number_parameters; ++index_v) /* EXPONENT_CHECK checks that an exponent x is within a valid range and, if not, reduces its magnitude to fit in the range. */ #define EXPONENT_CHECK(x) \ ((x) < min_exponent ? min_exponent : \ ((x) > max_exponent ? max_exponent : (x))) /* PARAMETER_RANGE_TOO_SMALL(x) checks if the range of parameter x is too small to work with If user_cost_function changes the parameter ranges, this test could be (and has been) used to adaptively bypass some parameters, e.g., depending on constraints. */ #define PARAMETER_RANGE_TOO_SMALL(x) \ (fabs(parameter_minimum[x] - parameter_maximum[x]) < (double) SMALL_FLOAT) /* INTEGER_PARAMETER(x) determines if the parameter is an integer type. */ #define INTEGER_PARAMETER(x) (parameter_type[x] == INTEGER_TYPE) /* ROW_COL_INDEX (i, j) converts from row i, column j to an index. */ #define ROW_COL_INDEX(i, j) (i + number_parameters * j) /* The State of the system, its parameters and their resulting function value */ typedef struct { double cost; double *parameter; } STATE; /* The 3 states that are kept track of during the annealing process */ STATE current_generated_state, last_saved_state, best_generated_state; /* The array of parameter bounds */ double *parameter_minimum, *parameter_maximum; /* The array of tangents (absolute value of the numerical derivatives), and the maximum |tangent| of the array */ double *tangents, maximum_tangent; /* The parameter curvature/covariance about the best state */ double *curvature; /* ratio of acceptances to generated points - determines when to test/reanneal */ double accepted_to_generated_ratio; /* temperature parameters */ double temperature_scale, temperature_scale_parameters; /* relative scalings of cost and parameters to temperature_scale */ double temperature_scale_cost; double *current_parameter_temperature, *initial_parameter_temperature; double current_cost_temperature, initial_cost_temperature; double temperature_rescale_power; /* used when applying REANNEAL_RESCALE */ double log_new_temperature_ratio; /* current temp = initial temp * exp(log_new_temperature_ratio) */ double one_over_number_parameters; /* 1/number_parameters */ int index_exit_v; /* information for vfsr_exit */ /* flag to determine if curvatures should be calculated */ int curvature_flag; /* counts of generated states and acceptances */ LONG_INT *index_parameter_generations; LONG_INT number_generated, best_number_generated_saved; LONG_INT recent_number_generated, number_parameters, number_accepted; LONG_INT recent_number_acceptances, index_cost_acceptances; LONG_INT number_acceptances_saved, best_number_accepted_saved; /* Flag indicates that the parameters generated were invalid according to the cost function validity criteria. */ int valid_state_generated_flag; LONG_INT number_invalid_generated_states, repeated_invalid_states; /* parameter type is real or integer */ int *parameter_type; /* used by EXPONENT_CHECK */ double max_exponent, min_exponent; /* used to index repeated and recursive calls to vfsr */ static int vfsr_open = FALSE; static int number_vfsr_open = 0; static int recursive_vfsr_open = 0; /* file ptr to output file */ FILE *ptr_vfsr_out; #if ADAPTIVE_OPTIONS /* global parameterization of DEFINE_OPTIONS */ double COST_PRECISION; int USER_INITIAL_PARAMETERS; double ACCEPTED_TO_GENERATED_RATIO; int LIMIT_ACCEPTANCES; double TEMPERATURE_RATIO_SCALE; double TEMPERATURE_ANNEAL_SCALE; double COST_PARAMETER_SCALE; int TESTING_FREQUENCY_MODULUS; int MAXIMUM_REANNEAL_INDEX; double REANNEAL_RESCALE; double INITIAL_PARAMETER_TEMPERATURE; int USER_INITIAL_PARAMETERS_TEMPS; int USER_INITIAL_COST_TEMP; int NUMBER_COST_SAMPLES; int MAXIMUM_COST_REPEAT; double DELTA_X; int INCLUDE_INTEGER_PARAMETERS; int ACTIVATE_REANNEAL; int LIMIT_INVALID_GENERATED_STATES; #endif /* system function prototypes */ #if HAVE_ANSI #if VFSR_PRINT #if 0 /* This block gave trouble under Ultrix */ int fprintf(FILE * fp, char *string,...); int fflush(FILE * fp); int fclose(FILE * fp); void exit(int code); #endif #if IO_PROTOTYPES int fprintf(); int fflush(); int fclose(); void exit(); #endif #if TIME_CALC void print_vfsr_time(char *message); void aux_print_vfsr_time(struct timeval *time, char *message); #endif #endif /* vfsr function prototypes */ void accept_new_state(double (*user_random_generator) ()); void generate_new_state(double (*user_random_generator) ()); void reanneal(void); void cost_derivatives(double (*user_cost_function) ()); double generate_vfsr_state(double temp, double (*user_random_generator) ()); double vfsr( double (*user_cost_function) (), double (*user_random_generator) (), int number_parameters, int *parameter_type, double *parameter_initial_final, double *parameter_minimum, double *parameter_maximum, double *tangents, double *curvature, int *exit_status, DEFINES * OPTIONS); void vfsr_exit(double (*user_cost_function) (), double *parameter_initial_final, double *final_cost, int *exit_status); #if VFSR_PRINT void print_state(void); #endif #else /* if HAVE_ANSI */ #if VFSR_PRINT #if IO_PROTOTYPES int fprintf(); int fflush(); int fclose(); #endif #if TIME_CALC void print_vfsr_time(); void aux_print_vfsr_time(); #endif #endif /* vfsr function prototypes */ void accept_new_state(); void generate_new_state(); void reanneal(); void cost_derivatives(); double generate_vfsr_state(); double vfsr(); void vfsr_exit(); #if VFSR_PRINT void print_state(); #endif #endif /* if HAVE_ANSI */