# Function Design: 4-Output Mapper Functions

Posted

Let's start our exploration of the new mapper functions with the 4-output mapper functions of 2, 3, and 4 arguments. In GeneXproTools these functions are represented by Map4A, Map4B, and Map4C, where the big letter at the end represents the number of arguments (A corresponds to 2, B to 3, and C to 4).

The Map4B and Map4C functions were the very first that I designed and tested (remember, I was trying to create functions with 3-4 discrete outputs that matched the argmin/argmax functions in performance), and both of them perform better than the argmax function of 4 arguments (98% hits for B, 99% for C, and 96% for the argmax).

I've already talked about the Map4B function in the post "Function Design: New 3-6 Output Functions" and as you can see from the code below, the Map4C function explores a similar design structure, with the difference that the middle point is in this case also determined independently by one of the arguments of the function.

The Map4A function is a late comer and is slightly inferior to the Map4B and C, but nonetheless performs slightly better than the argmax function of 4 arguments, even though it's only a function of 2 arguments (97% hits vs 96% for the argmax)!

Like I said, the Map4A function (and all mapper functions of the A series; I'll describe them in subsequent posts) was one of the latest mapper functions that I created. As they use only one argument for the map, I had to define a slack to generate the necessary number of intervals (here, for the Map4A function, we need to define 4 intervals for the four different outputs). And my first choice for the slack was 1000 but unfortunately it didn't work very well. I was very disappointed because I so wanted to create mapper functions of 2 arguments (functions of 2 arguments enjoy a special status in GeneXproTools because they require less bulky tree structures)! Just out of desperation I decided to try other values for the slack: 100, 10, and 1. And surprise: It made a huge difference, with 10 the best value for the Map4A function (a slack of 1 was the second best). (Who said all intervals are equal?)

For completeness I'm including here the C++ code for all the mappers of this series, including the Map4B function introduced in the post "Function Design: New 3-6 Output Functions":

// Map4A(x0,x1): 4-Output Mapper Function
const double SLACK = 10.0;
double output = 0.0;
if (x[1] < (x[0] - SLACK))
output = 0.0;
else if (x[1] >= (x[0] - SLACK) && x[1] < x[0])
output = 1.0;
else if (x[1] >= x[0] && x[1] < (x[0] + SLACK))
output = 2.0;
else if (x[1] >= (x[0] + SLACK))
output = 3.0;
return output;

// Map4B(x0,x1,x2): 4-Output Mapper Function
// evaluate min(x0,x1), max(x0,x1) and midrange
double min = x[0];
double max = x[1];
if (min > x[1])
{
min = x[1];
max = x[0];
}
double midrange = (max + min)/2.0;
double output = 0.0;
if (x[2] < min)
output = 0.0;
else if (x[2] >= min && x[2] < midrange)
output = 1.0;
else if (x[2] >= midrange && x[2] < max)
output = 2.0;
else if (x[2] >= max)
output = 3.0;
return output;

// Map4C(x0,x1,x2,x3): 4-Output Mapper Function
// evaluate min(x,y,z), max(x,y,z) and midleValue(x,y,z)
//
// evaluate min(x,y,z)
double min = x[0];
int argmin = 0;
if (min > x[1])
{
min = x[1];
argmin = 1;
}
if (min > x[2])
{
min = x[2];
argmin = 2;
}
// evaluate max(x,y,z)
double max = x[0];
int argmax = 0;
if (max < x[1])
{
max = x[1];
argmax = 1;
}
if (max < x[2])
{
max = x[2];
argmax = 2;
}
// evaluate midleValue(x,y,z)
double midleValue = x[2];
if (0 != argmin && 0 != argmax)
midleValue = x[0];
if (1 != argmin && 1 != argmax)
midleValue = x[1];

double output = 0.0;
if (x[3] < min)
output = 0.0;
else if (x[3] >= min && x[3] < midleValue)
output = 1.0;
else if (x[3] >= midleValue && x[3] < max)
output = 2.0;
else if (x[3] >= max)
output = 3.0;
return output;

In the next post I'll describe the 5-output mapper functions of 2, 3, and 4 arguments.

Author