The most common and simple way to use Visual Quantify is
by using its Graphical User Interface (GUI). However, a more
powerful and more complex way to use the package is provided
by its built-in API
library
functions which may be inserted into the test programs source code.
In this case, the access to the program is more complex but it offers
the interesting flexibility which is required for the use as accurate
fitness function in GA programming.
In order to to install the API functions properly, the header file
pure.h
must be
included into the test program's source code. The test program must be
recompiled and rebuilt. Finally, quantify may be called from a command
shell without the display of any windows on the screen.
The QuantifyClearData() function removes any data collected so far
from the system and resets all counters. This function must be called
before any recording is started. The function also indicates the begin of
a ``snapshot'', which may be stored separately into a file.
The functions QuantifyStartRecordingData() and
QuantifyStopRecordingData() are used in order to restrict the
gathering of timing data to the section of the program which is enclosed
by the two commands. This is usually the actual test procedure. It avoids
any computational overhead as only statements within the two function
calls are timed. QuantifySaveData() writes a previously taken
``snapshot'' into a binary or a text file, depending on a
command-line option.
The following source code examples show the usage of visual quantify for repeated program timing:
// fitness function in the GA program
double fitness (int size,
unsigned char* parameter_string,
char* exe_name) {
ofstream out;
out.open("qfyifce.dat",ios::binary); // write parameter
out.write(parameter_string,size); // to binary file
out.close();
if (call_qfy(exe_name,size) != 0) // call qantify and wait
return (-1.0);
// read the quantify result from file
// and return the fitness
return ((double)qfy_txt_scan(exe_name));
}
// create a new quantify process
int call_qfy (char* exe_name, int size) {
char str_size[8];
switch (fork()) {
case -1: perror("fork");
return(-1);
break;
case 0: {
ostrstream oss (str_size,8);
oss << size;
// call qantify with option /SaveTextData and
// Test Program <exe_name> which takes the
// parameter <str_size>
execlp("quantify", "quantify", "/save-text-data",
exe_name, str_size, NULL);
perror("execlp");
break;
}
default:
wait(); // for for quantify to return
}
return (0);
}
// scan quantify's result file for the fitness
int qfy_txt_scan (char* exe_name) {
const int LSZ = 256; // max size of input
const char* KEY = "function"; // keyword to search for
char line [LSZ]; // input read buffer
char name [LSZ]; // filename
ifstream in; // input file
char tok1[LSZ], tok2[LSZ]; // input line tokens
int tok3, tok4, tok5;
ostrstream oss (name,LSZ);
oss << exename << ".txt"; // strcat <exename>.txt
// read input file line by line until eof or key found
while (in.getline(line,LSZ,'\n')) {
istrstream ins (line, LSZ); // split line into tokens
ins >> tok1 >> tok2 >> tok3 >> tok4 >> tok5;
if (strcmp(tok1,KEY) == 0) { // keyword found
in.close();
return(tok5); // return F+D time (=fitness)
}
}
in.close();
return (-1);
}
// main program which is "instrumentalized" by quantify
int main (int argc, char* argv[]) {
int size;
unsigned char* buffer;
ifstream in;
istrstream iss (argv[1],8);
iss >> size;
buffer = new unsigned char[size];
in.open("qfyifce.dat", ios::in|ios::binary);
in.read(buffer,size);
in.close();
QuantifyClearData();
QuantifyStartRecordingData();
TestProgram (*(Test_Type*)&buffer); // call the test procedure
QuantifyStopRecordingData();
QuantifySaveData();
delete [] buffer;
}
As Quantify cannot be executed directly as daemon running in the
background and waiting for a client's request, a network interface
is obviously an appropriate solution. Basically, every type of
IPC
could be used, but the usage
of network sockets provides easy implementation, hardware
independence and distribution. In this case, Visual Quantify is started
in order to perform timing on a network server which executes the test
program. The network server is executed on a remote host waiting for
a GA process - the client - to send its produced input parameters.
Although, a socket implementation is already in use and has proved
valuable, a detailed description including code examples is beyond the
scope of this report.