I am currently trying to do some optimization for locations on a map using OpenMDAO 1.7.2. The (preexisting) modules that do the calculations only support integer coordinates (resolution of one meter).
For now I am optimizing using an IndepVarComp
for each direction each containing a float
vector. These values are then rounded before using them, but this is quite inefficient because the solver mainly tries variations smaller below one.
When I attempt to initialize an IndepVarComp
with an integer vector the first iteration works fine (uses inital values), but in the second iteration fails, because the data in IndepVarComp
is set to an empty ndarray
.
Looking through the OpenMDAO source code I found out that this is because
indep_var_comp._init_unknowns_dict['x']['size'] == 0
which happens in Component
's _add_variable()
method whenever the data type is not differentiable.
Here is an example problem which illustrates how defining an integer IndepVarComp
fails:
from openmdao.api import Component, Group, IndepVarComp, Problem, ScipyOptimizer
INITIAL_X = 1
class ResultCalculator(Component):
def __init__(self):
super(ResultCalculator, self).__init__()
self.add_param('x', INITIAL_X)
self.add_output('y', 0.)
def solve_nonlinear(self, params, unknowns, resids):
unknowns['y'] = (params['x'] - 3) ** 2 - 4
problem = Problem()
problem.root = Group()
problem.root.add('indep_var_comp', IndepVarComp('x', INITIAL_X))
problem.root.add('calculator', ResultCalculator())
problem.root.connect('indep_var_comp.x', 'calculator.x')
problem.driver = ScipyOptimizer()
problem.driver.options['optimizer'] = 'COBYLA'
problem.driver.add_desvar('indep_var_comp.x')
problem.driver.add_objective('calculator.y')
problem.setup()
problem.run()
Which fails with
ValueError: setting an array element with a sequence.
Note that everythings works out fine if I set INITIAL_X = 0.
.
How am I supposed to optimize for integers?
if you want to use integer variables, you need to pick a different kind of optimizer. You won't be able to force COBYLA to respect the integrality. Additionally, if you do have some kind of integer rounding causing discontinuities in your analyses then you really can't be using COBYLA (or any other continuous optimizer) at all. They all make a fundamental assumption about smoothness of the function which you would be violating.
It sounds like you should possibly consider using a particle swarm or genetic algorithm for your problem. Alternatively, you could focus on making the analyses smooth and differentiable and scale some of your inputs to get more reasonable resolution. You can also loosen the convergence tolerance of the optimizer to have it stop iterating once it gets below physical significance in your design variables.