"Scaler" умножается в два раза? - PullRequest
0 голосов
/ 26 февраля 2019

У меня всегда были некоторые проблемы с параметрами масштабирования в openmdao.Поскольку иногда масштабирование работает неявно во время решателей матрицы, а иногда - явно и т. Д. Теперь у меня есть проблема масштабирования ограничения и его записи.Я использовал пример Консольный луч

Я добавил масштабер = 2

    self.add_constraint('volume_comp.volume', equals=volume,scaler=2)

Я не изменил значение ограничения объема = 0,01.Если я установил Scaler = 1, записанный вывод объема ограничения будет равен 0,01 в конце оптимизации.Однако, если я установлю Scaler = 2, переменная громкости равна 0,04.А для Scaler = 10 объем вывода равен 1 и т. Д. Есть ли дополнительное умножение.

Оптимизированное значение не меняется независимо от того, что, как я предполагаю, ожидается, потому что это масштабирование только для нормализации (насколько я понимаю).

Ниже приведен пример строки измененного примера кода и рекордера, я использую OpenMDAO 2.5.0

from __future__ import division
import numpy as np

from openmdao.api import Group, IndepVarComp

from openmdao.test_suite.test_examples.beam_optimization.components.moment_comp import MomentOfInertiaComp
from openmdao.test_suite.test_examples.beam_optimization.components.local_stiffness_matrix_comp import LocalStiffnessMatrixComp
from openmdao.test_suite.test_examples.beam_optimization.components.states_comp import StatesComp
from openmdao.test_suite.test_examples.beam_optimization.components.displacements_comp import DisplacementsComp
from openmdao.test_suite.test_examples.beam_optimization.components.compliance_comp import ComplianceComp
from openmdao.test_suite.test_examples.beam_optimization.components.volume_comp import VolumeComp


class BeamGroup(Group):

    def initialize(self):
        self.options.declare('E')
        self.options.declare('L')
        self.options.declare('b')
        self.options.declare('volume')
        self.options.declare('num_elements', int)

    def setup(self):
        E = self.options['E']
        L = self.options['L']
        b = self.options['b']
        volume = self.options['volume']
        num_elements = self.options['num_elements']
        num_nodes = num_elements + 1

        force_vector = np.zeros(2 * num_nodes)
        force_vector[-2] = -1.

        inputs_comp = IndepVarComp()
        inputs_comp.add_output('h', shape=num_elements)
        self.add_subsystem('inputs_comp', inputs_comp)

        I_comp = MomentOfInertiaComp(num_elements=num_elements, b=b)
        self.add_subsystem('I_comp', I_comp)

        comp = LocalStiffnessMatrixComp(num_elements=num_elements, E=E, L=L)
        self.add_subsystem('local_stiffness_matrix_comp', comp)

        comp = StatesComp(num_elements=num_elements, force_vector=force_vector)
        self.add_subsystem('states_comp', comp)

        comp = DisplacementsComp(num_elements=num_elements)
        self.add_subsystem('displacements_comp', comp)

        comp = ComplianceComp(num_elements=num_elements, force_vector=force_vector)
        self.add_subsystem('compliance_comp', comp)

        comp = VolumeComp(num_elements=num_elements, b=b, L=L)
        self.add_subsystem('volume_comp', comp)

        self.connect('inputs_comp.h', 'I_comp.h')
        self.connect('I_comp.I', 'local_stiffness_matrix_comp.I')
        self.connect(
            'local_stiffness_matrix_comp.K_local',
            'states_comp.K_local')
        self.connect(
            'states_comp.d',
            'displacements_comp.d')
        self.connect(
            'displacements_comp.displacements',
            'compliance_comp.displacements')
        self.connect(
            'inputs_comp.h',
            'volume_comp.h')

        self.add_design_var('inputs_comp.h', lower=1e-2, upper=10.)
        self.add_objective('compliance_comp.compliance')
        self.add_constraint('volume_comp.volume', equals=volume,scaler=10)

import numpy as np

from openmdao.api import Problem, ScipyOptimizeDriver,SqliteRecorder

E = 1.
L = 1.
b = 0.1
volume = 0.01

num_elements = 50

prob = Problem(model=BeamGroup(E=E, L=L, b=b, volume=volume, num_elements=num_elements))

prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.driver.options['tol'] = 1e-9
prob.driver.options['disp'] = True
recorder = SqliteRecorder('abc.sql')
prob.driver.add_recorder(recorder)
prob.driver.recording_options['includes'] = []
prob.driver.recording_options['record_inputs'] = True
#        prob.driver.recording_options['record_outputs'] = True
prob.driver.recording_options['record_objectives'] = True
prob.driver.recording_options['record_constraints'] = True
prob.driver.recording_options['record_desvars'] = True
prob.driver.recording_options['record_derivatives'] = True
prob.setup()

prob.run_driver()

print(prob['inputs_comp.h'])
prob.cleanup()


#%%
import re
from openmdao.api import  CaseReader
import matplotlib.pyplot as plt
import numpy as np
import os,json as js    
import matplotlib

cr = CaseReader('abc.sql')
case_keys = cr.list_cases()
obj=[]
for i, case_key in enumerate(case_keys):
    case = cr.get_case(case_key)   
    derivs = cr.get_case(i).jacobian
#        for k in derivs:
#            print(k,derivs[k])

    recorded_objectives  = case.get_objectives()
    recorder_constraints = case.get_constraints()        
    recorder_desvars     = case.get_design_vars()        
    recorder_responses   = case.get_responses()        
    for k in recorder_desvars:
        print(k,recorder_desvars[k])
    for k in recorder_constraints:
        print(k,recorder_constraints[k])  
    for k in recorded_objectives:
        print(k,recorded_objectives[k])  
        obj.append(recorded_objectives[k])

    print('-----------')



#    
#print(obj)
#obj[2]=obj[1]
#print(len(obj))
plt.plot(obj,'*')

1 Ответ

0 голосов
/ 26 февраля 2019

Переменные в рекордере действительно масштабируются дважды.В драйвере значения масштабируются правильно.Вы можете сравнить его для последнего случая с кодом ниже.Масштабирование выполняется в _apply_voi_meta() в классе Case.

#%%

cr = CaseReader('abc.sql')
case_keys = cr.list_cases()
obj=[]
for i, case_key in enumerate(case_keys):
    case = cr.get_case(case_key)
    derivs = cr.get_case(i).jacobian
#        for k in derivs:
#            print(k,derivs[k])

    recorded_objectives  = case.get_objectives()
    recorder_constraints = case.get_constraints()
    recorder_desvars     = case.get_design_vars()
    recorder_responses   = case.get_responses()
    for k in recorder_desvars:
        print(k,recorder_desvars[k])
    for k in recorder_constraints:
        print(k,recorder_constraints[k])
    for k in recorded_objectives:
        print(k,recorded_objectives[k])
        obj.append(recorded_objectives[k])

    print('-----------')

print('\nDRIVER:\n\n')

for k, v in iteritems(driver.get_design_var_values()):
    print(k, v)
for k, v in iteritems(driver.get_constraint_values()):
    print(k, v)
for k, v in iteritems(driver.get_objective_values()):
    print(k, v)

Теперь ясно, что источником проблемы является рекордер.В вашем случае вы вызываете оба get_constraints() и get_responses() методы для этого случая.В этих методах изменяемые переменные масштабируются.Поэтому, когда вы возвращаете значение, переменная vals в _apply_voi_meta() также масштабируется.Сколько раз вы вызываете любую функцию, которая масштабирует одни и те же переменные, переменные будут масштабироваться при каждом вызове функции как побочный эффект.

См. Пример ниже:

#%%

cr = CaseReader('abc.sql')
case_keys = cr.list_cases()
obj=[]

scaled = True

for i, case_key in enumerate(case_keys):
    case = cr.get_case(case_key)
    derivs = cr.get_case(i).jacobian
#        for k in derivs:
#            print(k,derivs[k])

    recorded_objectives  = case.get_objectives(scaled=scaled)
    recorder_constraints = case.get_constraints(scaled=scaled)
    recorder_desvars     = case.get_design_vars()
    # recorder_responses   = case.get_responses(scaled=scaled)

    case.get_constraints(scaled=scaled)
    case.get_constraints(scaled=scaled)

    for k in recorder_desvars:
        print(k,recorder_desvars[k])
    for k in recorder_constraints:
        print(k,recorder_constraints[k])
    for k in recorded_objectives:
        print(k,recorded_objectives[k])
        obj.append(recorded_objectives[k])

    print('-----------')

print('\nDRIVER:\n\n')

for k, v in iteritems(driver.get_design_var_values()):
    print(k, v)
for k, v in iteritems(driver.get_constraint_values()):
    print(k, v)
for k, v in iteritems(driver.get_objective_values()):
    print(k, v)

Еслимасштабирующее устройство равно 10, ограничение будет в 1000 (или 10 ^ 3) раз превышать немасштабированное значение, потому что теперь я вызывал метод get_constraints() 3 раза.

...