Publicado em: 15/Jun/2020
Atualizado em: 22/Jun/2020
#C++ #cpp #otimização #optimlib

Otimização numérica em C++

A OptimLib é uma biblioteca C++ lightweight para otimização numérica de funções não lineares.

Instalação da optimlib

1git clone https://github.com/kthohr/optim.git
2cd optim
3./configure --header-only-version

Após os comandos acima é criado um diretório chamado header_only_version. A partir daí é só incluir este diretório nos flags de compilação: -Ialgum-lugar/header_only_version

Exemplo 1

Neste exemplo usaremos o método Differential Evolution (DE) que é uma busca genética estocástica para otimização global.

Localizar o mínimo da função $f(x) = x^2 - 5x + 6$.

Função exemplo para busca do mínimo.
Função exemplo para busca do mínimo.

A função a ser otimizada precisa ter o seguinte formato:

1double f( vetor_de_entrada, vetor_de_gradiente, parametros_adicionais )

Definindo nosso $f(x)$ usando o formato acima:

1double f( const arma::vec &vals_inp, arma::vec *grad_out, void *opt_data )
2{
3  const double x = vals_inp( 0 ); // Nosssa função é muito simples e só utiliza uma entrada
4  return x * x - 5 * x + 6;
5}

Realizando a otimização:

1arma::vec x = arma::ones( 1, 1 ) + 0.5; // Valor inicial 1.5
2if( optim::de( x, f, nullptr ) ) {
3  cout << "Mínimo para f(x) = x² - 5x + 6 => " << x << endl;
4  // Mínimo para f(x) = x² - 5x + 6 =>    2.5000
5}

Exemplo 2

A função anterior é muito bem comportada e sem mínimos locais. Vamos complicar um pouco.

Localizar o mínimo da função $f(x) = x^2 - 5x + 6 + 0.2\sin(10x)$.

Cálculo do valor mínimo.
Cálculo do valor mínimo.

Definindo a nova função:

1double g( const arma::vec &vals_inp, arma::vec *grad_out, void *opt_data )
2{
3  const double x  = vals_inp( 0 );
4  return x * x - 5 * x + 6 + 0.2 * sin( 10 * x );
5}

Realizando a otimização:

1arma::vec x = arma::ones( 1, 1 ) + 0.5; // Valor inicial 1.5
2if( optim::de( x, g, nullptr ) ) {
3  cout << "Mínimo para f(x) = x² - 5x + 6 + 0.2 sin( 10x ) => " << x << endl;
4  // Mínimo para f(x) = x² - 5x + 6 + 0.2 sin( 10x ) =>    2.3693
5}

Referências

comments powered by Disqus