Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOPT does not communicate the number of function evaluations to pagmo #25

Open
castanhas98 opened this issue Mar 28, 2022 · 2 comments · May be fixed by #26
Open

SNOPT does not communicate the number of function evaluations to pagmo #25

castanhas98 opened this issue Mar 28, 2022 · 2 comments · May be fixed by #26

Comments

@castanhas98
Copy link

castanhas98 commented Mar 28, 2022

As stated in the title, pagmo does not seem to be able to retrieve the number of function evaluations performed by SNOPT.

Below is an example similar to the one found in https://esa.github.io/pagmo_plugins_nonfree/quickstart.html with some changes.

int main( )
{
    // 1 - Instantiate a pagmo problem constructing it from the Rosenbrock UDP.
    problem prob{rosenbrock(30)};
    
    // 2 - Instantiate a pagmo_plugins_nonfree algorithm, in this case SNOPT. This assumes a library libsnopt7_c.so is
    ppnf::snopt7 algo(false, "./snopt-interface/lib/libsnopt7_c.so", 6u);
    algo.set_verbosity(1);

    // 3 - Instantiate a population with a single individual and random_seed = 0.
    population pop( prob, 1, 0 );

    // 4 - Print the initial population.
    std::cout << "Initial Population:" << std::endl;
    std::cout << pop << std::endl;

    std::cout.setstate(std::ios_base::failbit); // Preventing output from being printed to cout
    // 5 - Perform one generation of evolution with snopt7.
    pop = algo.evolve( pop );
    std::cout.clear(); // Allowing output to be printed to cout

    // 6 - Print the population after the evolution.
    std::cout << "Final Population:" << std::endl;
    std::cout << pop << std::endl;
    
    std::cout << "Actual number of fitness evaluations (algo.get_log().size()): " << algo.get_log().size() << std::endl;

    return 0;
}

This produces the following output:

Initial Population:
Problem name: Multidimensional Rosenbrock Function
	C++ class name: pagmo::rosenbrock

	Global dimension:			30
	Integer dimension:			0
	Fitness dimension:			1
	Number of objectives:			1
	Equality constraints dimension:		0
	Inequality constraints dimension:	0
	Lower bounds: [-5, -5, -5, -5, -5, ... ]
	Upper bounds: [10, 10, 10, 10, 10, ... ]
	Has batch fitness evaluation: false

	Has gradient: true
	User implemented gradient sparsity: false
	Expected gradients: 30
	Has hessians: false
	User implemented hessians sparsity: false

	Fitness evaluations: 1
	Gradient evaluations: 0

	Thread safety: constant

Population size: 1

List of individuals: 
#0:
	ID:			4880189657833503230
	Decision vector:	[3.89267, 7.66399, 7.86918, 7.70878, 4.35346, ... ]
	Fitness vector:		[3.34052e+06]

Champion decision vector: [3.89267, 7.66399, 7.86918, 7.70878, 4.35346, ... ]
Champion fitness: [3.34052e+06]

Final Population:
Problem name: Multidimensional Rosenbrock Function
	C++ class name: pagmo::rosenbrock

	Global dimension:			30
	Integer dimension:			0
	Fitness dimension:			1
	Number of objectives:			1
	Equality constraints dimension:		0
	Inequality constraints dimension:	0
	Lower bounds: [-5, -5, -5, -5, -5, ... ]
	Upper bounds: [10, 10, 10, 10, 10, ... ]
	Has batch fitness evaluation: false

	Has gradient: true
	User implemented gradient sparsity: false
	Expected gradients: 30
	Has hessians: false
	User implemented hessians sparsity: false

	Fitness evaluations: 1
	Gradient evaluations: 0

	Thread safety: constant

Population size: 1

List of individuals: 
#0:
	ID:			4880189657833503230
	Decision vector:	[1, 1, 1, 1, 1, ... ]
	Fitness vector:		[1.08934e-16]

Champion decision vector: [1, 1, 1, 1, 1, ... ]
Champion fitness: [1.08934e-16]

Actual number of fitness evaluations (algo.get_log().size()): 228

As it can be seen, the number of fitness evaluations indicated by the population is not the same as the number of lines (=function evaluations) of the log when the verbosity is set to 1.

@darioizzo
Copy link
Member

darioizzo commented Mar 28, 2022

Problem is revealed by the line:

https://github.com/esa/pagmo_plugins_nonfree/blob/master/src/snopt7.cpp#L715

the struct info contains a full instance of problem that is then copied .... a solution to try is to store a pointer rather than an instance as data member of the user_data struct:

@castanhas98
Copy link
Author

castanhas98 commented Apr 12, 2022

Problem is revealed by the line:

https://github.com/esa/pagmo_plugins_nonfree/blob/master/src/snopt7.cpp#L715

the struct info contains a full instance of problem that is then copied .... a solution to try is to store a pointer rather than an instance as data member of the user_data struct:

@darioizzo, I believe I managed to get your suggestion to work, but there is the need to remove the const qualifier from prob in the line below:

const auto &prob = pop.get_problem(); // This is a const reference, so using set_seed, for example, will not work

Both just removing the const in that line or making a const_cast to pagmo::problem * when assigning the problem in the user_data struct seem to do the trick.

info.m_prob = prob;

I honestly do not know which would be the preferred option, or if there are others that I am not considering. Any thoughts on this?

EDIT:
I believe I was creating a problem where there was none. user_data storing a pointer to a const pagmo::problem seems to be enough.

EDIT2:
I took the liberty to submit a pull request in an attempt to solve this issue. Will wait for feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants