 /* $Id: vfsr.h,v 1.1 1992/12/16 05:53:03 mume Exp $ vfsr.h */

 /* vfsr.h for Very Fast Simulated Reannealing */

#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>


extern double vfsr();
/* INCLUDE THIS FILE IF YOUR C COMPILER ONLY
   ACCEPTS IDENTIFIERS OF LESS THAN 32 CHARACTERS. */
/* #include long.names.h */
/*
#define TRUE	1
#define FALSE	0
*/
#define INTEGER_TYPE	1
#define REAL_TYPE	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

 /* DEFAULT PARAMETERS SETTINGS */
#ifndef HAVE_ANSI
#define HAVE_ANSI FALSE
#endif

#ifndef VFSR_PRINT
#define VFSR_PRINT TRUE
#endif

#ifndef VFSR_OUT
#define VFSR_OUT "vfsr_out"
#endif

#ifndef USER_INITIAL_PARAMETERS
#define USER_INITIAL_PARAMETERS TRUE
#endif

#ifndef ACCEPTED_TO_GENERATED_RATIO	/* determines when to test */
#define ACCEPTED_TO_GENERATED_RATIO 1.0E-4
#endif

#ifndef LIMIT_ACCEPTANCES	/* max number of acceptances */
#define LIMIT_ACCEPTANCES 1000
#endif

#ifndef TEMPERATURE_RATIO_SCALE
#define TEMPERATURE_RATIO_SCALE 1.0E-5
#endif

#ifndef TEMPERATURE_ANNEAL_SCALE
#define TEMPERATURE_ANNEAL_SCALE LIMIT_ACCEPTANCES/TEN
#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 1.0E8
#endif

#ifndef REANNEAL_RESCALE
#define REANNEAL_RESCALE 10.0
#endif

#ifndef INITIAL_PARAMETER_TEMPERATURE
#define INITIAL_PARAMETER_TEMPERATURE 1.0
#endif

#ifndef NUMBER_COST_SAMPLES
#define NUMBER_COST_SAMPLES 5
#endif

#ifndef MAXIMUM_COST_REPEAT
#define MAXIMUM_COST_REPEAT 5
#endif

#ifndef DELTA_X			/* delta of derivatives in cost_derivatives */
#define DELTA_X 0.001
#endif

#ifndef INCLUDE_INTEGER_PARAMETERS	/* in derivative calculations */
#define INCLUDE_INTEGER_PARAMETERS FALSE
#endif

#ifndef SMALL_FLOAT
#define SMALL_FLOAT 1.0E-12
#endif

#ifndef COST_PRECISION		/* precision at MAXIMUM_COST_REPEAT */
#define COST_PRECISION SMALL_FLOAT
#endif

#ifndef IO_PROTOTYPES
#define IO_PROTOTYPES FALSE
#endif

#ifndef ACTIVATE_REANNEAL
#define ACTIVATE_REANNEAL TRUE
#endif

 /* essential DEFINES and MACROS */
/* 
#define MAXIMUM_EXPONENT ((double) 2.302585/((double) SMALL_FLOAT))
*/
#define MAXIMUM_EXPONENT 700

 /* 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) \
 (fabs(x) < MAXIMUM_EXPONENT ? x : ((x * MAXIMUM_EXPONENT)/fabs(x)))

 /* PARAMETER_RANGE_TOO_SMALL(x)
    checks if the range of parameter x is too small to work with
    If user_cost_function were modified to pass 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 */
int *index_parameter_generations;
int number_generated, best_number_generated_saved;
int recent_number_generated, number_parameters, number_accepted;
int recent_number_acceptances, index_cost_acceptances;
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;
int number_invalid_generated_states;

/* parameter type is real or integer */
int *parameter_type;

 /* file ptr to output file */
FILE *ptr_vfsr_out;

 /* system function prototypes */
#if HAVE_ANSI
#if VFSR_PRINT
#if 0				/* This block gives trouble under some Ultrix */
int fprintf(FILE * fp, char *string,...);
int fflush(FILE * fp);
int fclose(FILE * fp);
void exit(int code);
#endif
#ifdef IO_PROTOTYPES
int fprintf();
int fflush();
int fclose();
void exit();
#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 *parameter_initial_final) */
	       double (*user_cost_function) (),
 /* (*double user_random_generator) (void) */
	       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);

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
#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 */
