numbbo / coco

Numerical Black-Box Optimization Benchmarking Framework
https://numbbo.github.io/coco
Other
261 stars 86 forks source link

Understand sharp ridge function #2277

Closed yedidyakfir closed 3 months ago

yedidyakfir commented 5 months ago

Hi, I am using the Coco dataset for my research. I am trying to reverse-engineer some of the functions. I went over the c code for the sharp ridge function. It seems the function equation is sqrt(sum(x_i ** 2)) + sum(x_i ** 2), but I cant find out the rotation and other manipulation you do for each instance of the function. Can you help me with that?

Thanks

FMGS666 commented 5 months ago

Hello,

the transformations are done in the f_sharp_ridge_bbob_problem_allocate function. If you want to find where these transformations are done you need to look at the f_sharp_ridge_bbob_problem_allocate function in the f_sharp_ridge.c file. You can see that all the transformations of the instance of the function are done in lines 82-106.

In general, the code of each test function follows pretty much the following structure:

f_<function-name>_raw which Implements the raw and unaltered function ($f:\Omega \rightarrow \mathbb{R}$ WITHOUT any random transformation) without connections to any COCO structures. It takes as input the decision vector $x\in\Omega$ and simply returns the scalar value $f(x)$

f_<function-name>_evaluate Which evaluates the solution on a given instance of coco_problem_t (passed as first input to the function) by wrapping around the f_<function-name>_raw function

f_<function-name>_bbob_problem_allocate which handles the actual allocation of the coco_problem_t instance and also computes all the random transformations.

I hope this could help

yedidyakfir commented 5 months ago

the instance of the function are done

Can you explain a bit more? I see there is a calculation of 2 rotation matrices there, but where do we apply them to the data? Or make any use of them? In other words, how do this lines affect the evaluate method?

brockho commented 5 months ago

FYI, the mathematical definitions of the bbob functions can be found here: https://numbbo.github.io/gforge/downloads/download16.00/bbobdocfunctions.pdf

FMGS666 commented 5 months ago

Let us only consider the transformation that shifts vertically the objective function.

For a given function $f: \mathbb{R}^d \rightarrow \mathbb{R}$ and a solution $x \in \mathbb{R}^d$, this transformation is simply given by $f(x) + f{opt}$ where $f{opt} \in \mathbb{R}$ is determined in a pseudo random fashion

Let's ignore now how to determine the value of $f_{opt} $ and let's imagine that we have computed it and we have it stored in a double variable named fopt (You can see that it is computed by using the bbob2009_compute_fopt function)

Each transformation is defined as a wrapper around the coco_problem_t instance that implements the target transformation by nesting coco_problem_t inside each other (using coco_problem_t -> data and coco_problem_transformed_data_t -> inner_problem) and wrapping around the coco_problem_t->evaluate_function member function to apply the desired transformation at each nesting level.

In the f_sharp_ridge_bbob_problem_allocate function, still at the beginning, we read the declaration of a NULL pointer to a coco_problem_t:

  coco_problem_t *problem = NULL;

Now the problem is initialized by means of the f_sharp_ridge_allocate that allocates the coco_problem_t for the sharp ridge function with the following line

  problem = f_sharp_ridge_allocate(dimension);

The next line reads:

  problem = transform_obj_shift(problem, fopt);

This function returns the wrapped problem that applies the transformation as I mentioned before.

You can think of this new problem as a wrapper around the initial inner problem (i.e.: the one that we have allocated with the f_sharp_ridge_allocate function), whose evaluate_function member function calls the evaluate_function of the inner problem (in our case f_sharp_ridge_evaluate) and adds fopt to its result.

after this line the new problem variable will be the transformed version of the problem, while the original problem will end up in problem->data->inner_problem, if I am not wrong.

When we call the problem->evaluate_function member function, we call it on the new "external" problem and what will actually happen (in a stylized synthesis) is that we will be first calling problem->data->inner_problem and then applying the transformation, so that we will be returning the wanted (transformed) value.

I hope this was clearer.

olafmersmann commented 3 months ago

Can this issue be closed, or are there open questions left about the function definition?