Как передавать строковые значения между компонентами OpenMDAO?

Я хотел бы иметь возможность передавать строковые значения между компонентами. Возможно ли это в последней версии OpenMDAO или это будет возможно в будущих выпусках?

Если я правильно понимаю, то передача строк поддерживалась в более ранних выпусках OpenMDAO (V<=1) с передачей по объекту. В настоящее время я использую обходной путь, при котором строковые входные и выходные данные моих инструментов записываются в отдельные файлы и при необходимости берутся из этих файлов. Тогда это выходит за рамки модели OpenMDAO.

Вот небольшой пример типа модели, которая будет поддерживаться, если строки можно использовать в качестве входных и выходных данных. Это, конечно, просто демонстрационный случай.

from openmdao.core.explicitcomponent import ExplicitComponent
from openmdao.core.group import Group
from openmdao.core.indepvarcomp import IndepVarComp
from openmdao.core.problem import Problem
from openmdao.devtools.problem_viewer.problem_viewer import view_model


class PreProcessor(ExplicitComponent):

    def setup(self):
        self.add_input('a', val=0.)

        self.add_output('para_shape', val='hill')

    def compute(self, inputs, outputs):
        if inputs['a'] <= 0.:
            outputs['para_shape'] = 'hill'
        else:
            outputs['para_shape'] = 'canyon'


class Parabola(ExplicitComponent):

    def setup(self):
        self.add_input('x', val=0.)
        self.add_input('para_shape', val='hill')

        self.add_output('y', val=0.)

    def compute(self, inputs, outputs):
        if inputs['para_shape'] == 'hill':
            outputs['y'] = -inputs['x']**2
        elif inputs['para_shape'] == 'canyon':
            outputs['y'] = inputs['x']**2
        else:
            raise IOError('Invalid "para_shape" value "{}" provided.'.format(inputs['para_shape']))


if __name__ == "__main__":

    model = Group()
    ivc = IndepVarComp()
    ivc.add_output('a', 2.)
    ivc.add_output('x', 4.)
    model.add_subsystem('vars', ivc, promotes=['*'])
    model.add_subsystem('preprocessor', PreProcessor(), promotes=['*'])
    model.add_subsystem('parabola', Parabola(), promotes=['*'])

    prob = Problem(model)
    prob.setup()
    view_model(prob, outfile='n2_pass_by_object_example.html')

    prob.run_model()

Если я запущу это, я получу ValueError то could not convert string to float: hill, чего и следовало ожидать. Мне просто интересно, есть ли способ заставить это работать, сохраняя para_shape как строковый вывод PreProcessor и строковый ввод для Parabola.

Кроме того, в моем случае было бы просто удобно передавать строки, я подумал, что это также может быть полезно, когда используются алгоритмы оптимизации, поддерживающие дискретные значения, например, с генетическим алгоритмом. В этих алгоритмах para_shape может быть проектной переменной с возможными значениями hill или canyon. За кулисами такая строковая переменная, вероятно, будет сопоставлена ​​с целочисленным значением, например 0:hill, 1:canyon.

Таким образом, мой вопрос: будет ли реализована передача по объекту (или аналогичная возможность, которая позволяет мне определять строковый ввод/вывод) для OpenMDAO 2 или уже есть способ сделать это?

В чем разница между методом "==" и equals()
В чем разница между методом "==" и equals()
Это один из наиболее часто задаваемых вопросов новичкам на собеседовании. Давайте обсудим его на примере.
Замена символа по определенному индексу в JavaScript
Замена символа по определенному индексу в JavaScript
В JavaScript существует несколько способов заменить символ в строке по определенному индексу.
1
0
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошая новость заключается в том, что текущая версия OpenMDAO поддерживает дискретные переменные. Я обновил ваш пример, чтобы использовать текущий синтаксис для объявления дискретных переменных и передачи их функции вычисления. По сути, изменения заключаются в том, что вам нужно объявлять дискретные переменные с помощью add_discrete_input и add_discrete_output. Кроме того, вы должны добавить discrete_inputs и discrete_outputs в качестве аргументов к вашей функции compute, чтобы новая версия выглядела так: def compute(self, inputs, outputs, discrete_inputs, discrete_outputs). Также обратите внимание, что другие функции, такие как compute_partials, compute_jacvec_product и другие, также требуют дополнительных дискретных аргументов, если ваш компонент использует их.

Плохая новость заключается в том, что ваш пример выявил ошибку в view_model. Похоже, что view_model в настоящее время не поддерживает должным образом дискретные переменные. Я поместил ошибку в наш трекер ошибок, описывающую проблему, так что, надеюсь, мы скоро ее исправим.

from openmdao.core.explicitcomponent import ExplicitComponent
from openmdao.core.group import Group
from openmdao.core.indepvarcomp import IndepVarComp
from openmdao.core.problem import Problem
from openmdao.devtools.problem_viewer.problem_viewer import view_model


class PreProcessor(ExplicitComponent):

    def setup(self):
        self.add_input('a', val=0.)

        self.add_discrete_output('para_shape', val='hill')

    def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
        if inputs['a'] <= 0.:
            discrete_outputs['para_shape'] = 'hill'
        else:
            discrete_outputs['para_shape'] = 'canyon'


class Parabola(ExplicitComponent):

    def setup(self):
        self.add_input('x', val=0.)
        self.add_discrete_input('para_shape', val='hill')

        self.add_output('y', val=0.)

    def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
        if discrete_inputs['para_shape'] == 'hill':
            outputs['y'] = -inputs['x']**2
        elif discrete_inputs['para_shape'] == 'canyon':
            outputs['y'] = inputs['x']**2
        else:
            raise IOError('Invalid "para_shape" value "{}" provided.'.format(inputs['para_shape']))


if __name__ == "__main__":

    model = Group()
    ivc = IndepVarComp()
    ivc.add_output('a', 2.)
    ivc.add_output('x', 4.)
    model.add_subsystem('vars', ivc, promotes=['*'])
    model.add_subsystem('preprocessor', PreProcessor(), promotes=['*'])
    model.add_subsystem('parabola', Parabola(), promotes=['*'])

    prob = Problem(model)
    prob.setup()
    view_model(prob, outfile='n2_pass_by_object_example.html')
    prob.run_model()

Фантастика, это работает как шарм. Я думаю, что вы не предоставили обновленный код, возможно, случайно скопировали старый?

Imco van Gent 03.05.2019 15:22

Хорошо, может быть, предложением по улучшению, чтобы направить пользователя к потенциальному решению, было бы изменить сообщение ValueError на что-то вроде: ValueError: Could not convert string to float: hill. For string values, use discrete_inputs / _outputs in the component methods. Просто идея! :)

Imco van Gent 04.05.2019 12:39

Другие вопросы по теме