在pyomo中优化Fortran功能 [英] Optimizing Fortran function in pyomo

查看:211
本文介绍了在pyomo中优化Fortran功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望使用Pyomo优化Fortran函数.目标函数和约束都用Fortran编写.根据此处给出的答案,我们可以使用ExternalFunction表达式对象.但是,即使是最简单的功能,我也无法获得结果.下面给出的是一个可复制的示例,该示例由Fortran函数,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. 对于我的整个项目,我将不得不限制Fortran本身.约束子例程将返回一个实数,该实数将使用pyomo进行限制.如何为这些类型的约束建模?

  3. 我假设Pyomo将这个黑盒视为非线性优化.因此,我正在使用ipopt求解器.这个假设正确吗?

软件包的版本-

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

  2. ipopt-Ipopt 3.12.8

  3. f2py-与numpy 1.16.2一起安装

感谢您的帮助!

解决方案

如果您不受限于 Pyomo 您可以使用出色的 Pygmo 软件包,该软件包可为包括黑盒求解器在内的各种问题提供求解器. /p>

这里有一个小例子,说明如何在连续受限的单目标测试问题上使用它:

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)

然后,您只需要在适应性函数中处理连接"您的Fortran代码即可.

希望这会有所帮助!

I wish to optimize a Fortran function using Pyomo. Both the objective function and the constraints are are written in Fortran. Based on the answer given here, we can use ExternalFunction expression object. But I am not able to get the results even for the simplest function. Given below is a reproducible example which consists of the Fortran function, the python (Python 2.7.12) script, the commands executed for optimization and the error.

Fortran function file (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 script (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)

Commands executed at the terminal -

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

Error -

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

I have given only small portion of the error which I thought was relevant.

Given this, I have a the following questions -

  1. How to successfully solve this uncostrained optimization problem using pyomo?

  2. For my complete project, I will have to give constraints in Fortran itself. The constraint subroutines will return a real number which will be bounded using pyomo. How to model these type of constraints?

  3. I am assuming that Pyomo takes this blackbox as non-linear optimization. Hence, I am using ipopt solver. Is this assumption correct?

The versions of packages -

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

  2. ipopt - Ipopt 3.12.8

  3. f2py - installed along with numpy 1.16.2

Thanks for your help!

解决方案

If you are not bound to Pyomo you could use the excellent Pygmo package which offers solvers for different kinds of problems including blackbox solvers.

Here's a small example on how to use it on a continuous constrained single objective test problem:

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)

You would then just have to deal with "interfacing" your Fortran code within the fitness function.

Hope this helps!

这篇关于在pyomo中优化Fortran功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆