/* $Id: asa.h,v 2.3 1993/12/22 04:47:40 ingber Exp ingber $ */ /* asa.h for Adaptive Simulated Annealing */ #include #include #include #include /* misc defs on most machines */ #define TRUE 1 #define FALSE 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 */ /* Pre-Compile Options */ #ifndef ASA_TEST #define ASA_TEST FALSE #endif #ifndef ASA_TEMPLATE #define ASA_TEMPLATE FALSE #endif #ifndef HAVE_ANSI #define HAVE_ANSI TRUE #endif #ifndef IO_PROTOTYPES #define IO_PROTOTYPES TRUE #endif #ifndef TIME_CALC #define TIME_CALC FALSE #endif #ifndef TIME_STD #define TIME_STD FALSE #endif #if TIME_CALC #if TIME_STD #include #endif #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 #ifndef INT_ALLOC #define INT_ALLOC FALSE #endif #if INT_ALLOC #define ALLOC_INT int #else #define ALLOC_INT LONG_INT #endif #define INTEGER_TYPE ((int) 1) #define REAL_TYPE ((int) -1) #define INTEGER_NO_REANNEAL ((int) 2) #define REAL_NO_REANNEAL ((int) -2) /* You can define SMALL_FLOAT to better correlate to your machine's precision, i.e., as used in asa */ #ifndef SMALL_FLOAT #define SMALL_FLOAT 1.0E-18 #endif /* You can define your machine's maximum and minimum doubles here */ #ifndef MIN_DOUBLE #define MIN_DOUBLE SMALL_FLOAT #endif #ifndef MAX_DOUBLE #define MAX_DOUBLE (1.0/SMALL_FLOAT) #endif #ifndef EPS_DOUBLE #define EPS_DOUBLE SMALL_FLOAT #endif /* Set this to TRUE to self-optimize the Program Options */ #ifndef SELF_OPTIMIZE #define SELF_OPTIMIZE FALSE #endif #ifndef OPTIONAL_DATA #define OPTIONAL_DATA FALSE #endif /* Set this to TRUE to override the P_TEMP_TOO_SMALL test */ #ifndef NO_PARAM_TEMP_TEST #define NO_PARAM_TEMP_TEST FALSE #endif /* Set this to TRUE to override the C_TEMP_TOO_SMALL test */ #ifndef NO_COST_TEMP_TEST #define NO_COST_TEMP_TEST FALSE #endif /* Printing Options */ #ifndef ASA_PRINT #define ASA_PRINT TRUE #endif #ifndef ASA_OUT #define ASA_OUT "asa_out" #endif /* You can set ASA_PRINT_INTERMED to TRUE to print out intermediate data when SELF_OPTIMIZE is set to TRUE */ #ifndef ASA_PRINT_INTERMED #if SELF_OPTIMIZE #define ASA_PRINT_INTERMED FALSE #else #define ASA_PRINT_INTERMED TRUE #endif #endif #ifndef ASA_PRINT_MORE #define ASA_PRINT_MORE FALSE #endif #ifndef USER_ASA_OUT #define USER_ASA_OUT FALSE #endif #ifndef OPTIONS_FILE #define OPTIONS_FILE FALSE #endif /* Program Options */ typedef struct { int LIMIT_ACCEPTANCES; int LIMIT_INVALID_GENERATED_STATES; double ACCEPTED_TO_GENERATED_RATIO; double COST_PRECISION; int MAXIMUM_COST_REPEAT; int NUMBER_COST_SAMPLES; double TEMPERATURE_RATIO_SCALE; double COST_PARAMETER_SCALE; double TEMPERATURE_ANNEAL_SCALE; int USER_INITIAL_COST_TEMP; double *user_cost_temperature; int INCLUDE_INTEGER_PARAMETERS; int USER_INITIAL_PARAMETERS; double INITIAL_PARAMETER_TEMPERATURE; int RATIO_TEMPERATURE_SCALES; double *user_temperature_ratio; int USER_INITIAL_PARAMETERS_TEMPS; double *user_parameter_temperature; int TESTING_FREQUENCY_MODULUS; int ACTIVATE_REANNEAL; double REANNEAL_RESCALE; LONG_INT MAXIMUM_REANNEAL_INDEX; double DELTA_X; int DELTA_PARAMETERS; double *user_delta_parameter; int CURVATURE_0; int QUENCH_PARAMETERS; double *user_quench_param_scale; int QUENCH_COST; double *user_quench_cost_scale; #if OPTIONAL_DATA double *asa_data; #endif #if USER_ASA_OUT char *asa_out_file; #endif } DEFINES; /* The state of the system in terms of parameters and function value */ typedef struct { double cost; double *parameter; } STATE; /* essential MACROS */ /* REANNEAL_FUNCTION(temperature, tangent, max_tangent) determines the reannealed temperature. */ #define REANNEAL_FUNCTION(temperature, tangent, max_tangent) \ (temperature * (max_tangent / tangent)) /* IABS(i) absolute value for integers, in stdlib.h on _some_ machines */ #define IABS(i) ((i) < 0? -(i) : (i)) /* NO_REANNEAL(x) can determine whether to calculate derivatives. */ #define NO_REANNEAL(x) (IABS(parameter_type[x]) == 2) /* 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, adjusts its magnitude to fit in the range. */ #define MIN_EXPONENT (0.9 * log((double) MIN_DOUBLE)) #define MAX_EXPONENT (0.9 * log((double) MAX_DOUBLE)) #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 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) EPS_DOUBLE) /* INTEGER_PARAMETER(x) determines if the parameter is an integer type. */ #define INTEGER_PARAMETER(x) (parameter_type[x] > 0) /* ROW_COL_INDEX(i, j) converts from row i, column j to an index. */ #define ROW_COL_INDEX(i, j) ((i) + *number_parameters * (j)) #if HAVE_ANSI /* system function prototypes */ #if ASA_PRINT #if IO_PROTOTYPES int fprintf(); int fflush(); int fclose(); void exit(); #endif #if TIME_CALC void print_asa_time(char *message, FILE * ptr_asa_out); void aux_print_asa_time(struct timeval *time, char *message, FILE * ptr_asa_out); #if TIME_STD int syscall(int sys_option, int who, struct rusage *usage); #else int getrusage(int who, struct rusage *usage); #endif #endif #endif /* asa function prototypes */ void accept_new_state(double (*user_random_generator) (), double *parameter_minimum, double *parameter_maximum, double *current_cost_temperature, ALLOC_INT * number_parameters, LONG_INT * recent_number_acceptances, LONG_INT * number_accepted, LONG_INT * index_cost_acceptances, LONG_INT * number_acceptances_saved, LONG_INT * recent_number_generated, LONG_INT * number_generated, LONG_INT * index_parameter_generations, STATE * current_generated_state, STATE * last_saved_state); void generate_new_state(double (*user_random_generator) (), double *parameter_minimum, double *parameter_maximum, double *current_parameter_temperature, ALLOC_INT * number_parameters, int *parameter_type, STATE * current_generated_state, STATE * last_saved_state); void reanneal(double *parameter_minimum, double *parameter_maximum, double *tangents, double *maximum_tangent, double *current_cost_temperature, double *initial_cost_temperature, double *temperature_scale_cost, double *current_user_parameter_temp, double *initial_user_parameter_temp, double *temperature_scale_parameters, double *quench_param, double *quench_cost, ALLOC_INT * number_parameters, int *parameter_type, LONG_INT * index_cost_acceptances, LONG_INT * index_parameter_generations, STATE * last_saved_state, STATE * best_generated_state, DEFINES * OPTIONS); void cost_derivatives(double (*user_cost_function) (), double *parameter_minimum, double *parameter_maximum, double *tangents, double *curvature, double *maximum_tangent, double *delta_parameter, ALLOC_INT * number_parameters, int *parameter_type, int *exit_status, int *curvature_flag, int *valid_state_generated_flag, LONG_INT * number_invalid_generated_states, STATE * current_generated_state, STATE * best_generated_state, FILE * ptr_asa_out, DEFINES * OPTIONS); double generate_asa_state(double (*user_random_generator) (), double *temp); double asa(double (*user_cost_function) (), double (*user_random_generator) (), double *parameter_initial_final, double *parameter_minimum, double *parameter_maximum, double *tangents, double *curvature, ALLOC_INT * number_parameters, int *parameter_type, int *valid_state_generated_flag, int *exit_status, DEFINES * OPTIONS); void asa_exit(double (*user_cost_function) (), double *final_cost, double *parameter_initial_final, double *parameter_minimum, double *parameter_maximum, double *tangents, double *curvature, double *maximum_tangent, double *delta_parameter, double *current_cost_temperature, double *initial_user_parameter_temp, double *current_user_parameter_temp, double *temperature_scale_parameters, double *accepted_to_generated_ratio, ALLOC_INT * number_parameters, int *parameter_type, int *valid_state_generated_flag, int *exit_status, ALLOC_INT * index_exit_v, LONG_INT * number_accepted, LONG_INT * best_number_accepted_saved, LONG_INT * index_cost_acceptances, LONG_INT * number_generated, LONG_INT * number_invalid_generated_states, LONG_INT * index_parameter_generations, LONG_INT * best_number_generated_saved, STATE * current_generated_state, STATE * last_saved_state, STATE * best_generated_state, FILE * ptr_asa_out, DEFINES * OPTIONS); #if ASA_PRINT void print_state(double *parameter_minimum, double *parameter_maximum, double *tangents, double *curvature, double *current_cost_temperature, double *current_user_parameter_temp, double *accepted_to_generated_ratio, ALLOC_INT * number_parameters, int *curvature_flag, LONG_INT * number_accepted, LONG_INT * index_cost_acceptances, LONG_INT * number_generated, LONG_INT * number_invalid_generated_states, STATE * last_saved_state, STATE * best_generated_state, FILE * ptr_asa_out, DEFINES * OPTIONS); #endif #else /* if HAVE_ANSI */ #if ASA_PRINT #if IO_PROTOTYPES int fprintf(); int fflush(); int fclose(); #endif #if TIME_CALC void print_asa_time(); void aux_print_asa_time(); #if TIME_STD int syscall(); #else int getrusage(); #endif #endif #endif void accept_new_state(); void generate_new_state(); void reanneal(); void cost_derivatives(); double generate_asa_state(); double asa(); void asa_exit(); #if ASA_PRINT void print_state(); #endif #endif /* if HAVE_ANSI */ #ifndef __GNUC__ /* this can be useful when using gcc */ #define __GNUC__ FALSE #endif