Оптимизация функции Фортрана в pyomo - PullRequest
0 голосов
/ 15 марта 2019

Я хочу оптимизировать функцию Фортрана, используя Pyomo. И целевая функция, и ограничения написаны на фортране. Основываясь на ответе здесь , мы можем использовать ExternalFunction объект выражения. Но я не могу получить результаты даже для самой простой функции. Ниже приведен воспроизводимый пример, который состоит из функции Фортрана, скрипта python (Python 2.7.12), команд, выполняемых для оптимизации, и ошибки.

Файл функции Fortran (funcs.f) -

  SUBROUTINE OBJ1(ARG,OBJ)
  DOUBLE PRECISION, INTENT(IN) :: ARG(2)
  DOUBLE PRECISION, INTENT(OUT) :: OBJ
  OBJ = ARG(1)+ARG(2)
  RETURN
  END SUBROUTINE

Python-скрипт (pytest.py) -

import funcs
from pyomo.environ import *
from pyomo.opt import *
from pyomo.core import *

m = ConcreteModel()
m.a = Var(RangeSet(1,2),within=NonNegativeReals,bounds=(0,10))
m.f = ExternalFunction(library='funcs.so',function='OBJ1')
expr = m.f(m.a)
m.obj = Objective(expr=expr,sense=minimize)

opt = SolverFactory('ipopt')
results = opt.solve(m,tee=True)
print(results)

Команды, выполняемые на терминале -

>> f2py -c -m funcs funcs.f
>> python pytest.py

Ошибка -

File "/usr/local/lib/python2.7/dist-packages/pyomo/core/base/external.py", line 160, in load_library
FUNCADD(('funcadd_ASL', self._so))(byref(AE))
AttributeError: /home/utkarsh/Desktop/python/modules/blackboxOptimization/funcs.so: undefined symbol: funcadd_ASL

Я дал лишь небольшую часть ошибки, которая, на мой взгляд, была уместна.

Учитывая это, у меня есть следующие вопросы -

  1. Как успешно решить эту необусловленную задачу оптимизации с помощью pyomo?

  2. Для моего полного проекта мне придется дать ограничения в самом Фортране. Подпрограммы ограничения вернут действительное число, которое будет ограничено с помощью pyomo. Как смоделировать этот тип ограничений?

  3. Я предполагаю, что Pyomo использует этот черный ящик как нелинейную оптимизацию. Следовательно, я использую ipopt решатель. Это предположение верно?

Версии пакетов -

  1. Pyomo - 5.5.1 (VOTD) (CPython 2.7.12 в Linux 4.4.0-127-generic)

  2. ipopt - Ipopt 3.12.8

  3. f2py - устанавливается вместе с numpy 1.16.2

Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 02 мая 2019

Если вы не связаны с Pyomo , вы можете использовать превосходный пакет Pygmo , который предлагает решатели для различных типов задач, включая решатели для черного ящика.

Вот небольшойпример того, как использовать его в одной задаче непрерывного ограниченного одиночного теста:

import pygmo as pg
import pandas as pd


class Rosenbrock():
    """Rosenbrock function constrained to a disk.

    See: https://en.wikipedia.org/wiki/Test_functions_for_optimization
    """

    def fitness(self, x):
        """Evaluate fitness.

        Instead of the Rosenbrock function you could call your Fortran
        code here e.g. by using F2PY: https://www.numfys.net/howto/F2PY/
        """
        obj = (1-x[0])**2+100*(x[1]-x[0]**2)**2
        ineq = x[0]**2+x[1]**2-2
        return [obj, ineq]

    def get_bounds(self):
        """Return boundaries."""
        return ([-1.5]*2, [1.5]*2)

    def get_nic(self):
        """Determine number of inequalities."""
        return 1


# set up and solve problem
pro = pg.problem(Rosenbrock())
pop = pg.population(pro, size=200)
# see: https://github.com/esa/pagmo2/blob/master/include/pagmo/algorithms/
algo = pg.algorithm(pg.ihs(gen=10000))
algo.set_verbosity(100)
pop = algo.evolve(pop)

# extract solutions
fits = pd.DataFrame(pop.get_f())
vectors = pd.DataFrame(pop.get_x())
best_idx = pop.best_idx()
best_vector = vectors.loc[best_idx].to_frame().T
best_fitness = fits.loc[best_idx].to_frame().T

print(best_vector)
print(best_fitness)

Тогда вам просто придется иметь дело с "сопряжением" вашего кода Фортрана с функцией фитнеса.

Надеждаэто помогает!

...