# Path: openlego/utils/general_utils.py
# def str_to_valid_sys_name(string):
#     # type: (str) -> str
#     """Ensures a given string is a valid OpenMDAO system name."""
#     sys_name = re_sys_name_char.sub('', string)
#     while not re_sys_name_starts.match(sys_name):
#         sys_name = sys_name[1:]
#     return sys_name
# 
# def unscale_value(v, ref0, ref):
#     # TODO: add docstring
#     if isinstance(v, list):
#         v = np.array(v)
#     return v*(ref-ref0)+ref0
# 
# def scale_value(v, adder, scaler):
#     # TODO: add docstring
#     if adder is None:
#         adder = 0.
#     if scaler is None:
#         scaler = 1.
#     if isinstance(v, list):
#         v = np.array(v)
#     return (v + adder) * scaler
# 
# Path: openlego/utils/xml_utils.py
# def param_to_xpath(param):
#     # type: (str) -> str
#     """Convert an ``OpenMDAO`` parameter name to the corresponding XML XPath.
# 
#     This function is the inverse of `xpath_to_param()`.
# 
#     Parameters
#     ----------
#         param : str
#             Valid ``OpenMDAO`` parameter name.
# 
#     Returns
#     -------
#         str
#             Corresponding XML XPath.
#     """
#     xpath = param.replace(repl_emm, repl_emm_inv)
#     xpath = xpath.replace(repl_qtm, repl_qtm_inv)
#     xpath = xpath.replace(repl_str, repl_str_inv)
#     xpath = xpath.replace(repl_dot, repl_dot_inv)
#     xpath = re_ind_inv.sub(repl_ind_inv, xpath)
#     xpath = re_atr_inv.sub(repl_atr_inv, xpath)
#     return xpath


import copy
import os
import pickle
import numpy as np
import plotly
import plotly.graph_objs as go
from math import isnan as isnan
from typing import List
from openmdao.api import NonlinearBlockGS
from openmdao.core.analysis_error import AnalysisError
from openmdao.recorders.recording_iteration_stack import Recording
from openmdao.utils.general_utils import format_as_float_or_array
from openlego.utils.general_utils import str_to_valid_sys_name, unscale_value, scale_value
from openlego.utils.xml_utils import param_to_xpath
                                                if i > 0 else "..."))

        # Constraints
        print('CONSTRAINTS')
        for var_name in sorted(self.OPT_CON_VALUES.keys()):
            print(var_name)
            attrbs = self.ATTRBS_CON_VALUES[var_name]
            if attrbs['equals'] is not None:
                print('{} (== {})\n'.format(self.OPT_CON_VALUES[var_name][i][0], attrbs['equals']))
            elif attrbs['lower'] is not None or attrbs['upper'] is not None:
                print('{} (> {}, < {})\n'.format(self.OPT_CON_VALUES[var_name][i][0],
                                                 attrbs['lower'], attrbs['upper']))
            else:
                print('{} (unbounded)\n')

        # Objectives
        print('OBJECTIVE(S)')
        for var_name in sorted(self.OPT_OBJ_VALUES.keys()):
            print(var_name)
            print('{}\n'.format(self.OPT_OBJ_VALUES[var_name][i][0]))

    def _plot_history(self):
        # type: () -> None
        """Plot the results of the last B2k iteration in the browser."""
        traces_des_vars = []
        des_var_names = sorted(self.OPT_DV_VALUES.keys())
        legend_entries = [x.split('/')[-1] for x in des_var_names]
        for var_name, legend_name in zip(des_var_names, legend_entries):
            ref0s = self.REF0_VALUES[var_name]
            refs = self.REF_VALUES[var_name]

# Path: openlego/utils/general_utils.py
# def str_to_valid_sys_name(string):
#     # type: (str) -> str
#     """Ensures a given string is a valid OpenMDAO system name."""
#     sys_name = re_sys_name_char.sub('', string)
#     while not re_sys_name_starts.match(sys_name):
#         sys_name = sys_name[1:]
#     return sys_name
# 
# def unscale_value(v, ref0, ref):
#     # TODO: add docstring
#     if isinstance(v, list):
#         v = np.array(v)
#     return v*(ref-ref0)+ref0
# 
# def scale_value(v, adder, scaler):
#     # TODO: add docstring
#     if adder is None:
#         adder = 0.
#     if scaler is None:
#         scaler = 1.
#     if isinstance(v, list):
#         v = np.array(v)
#     return (v + adder) * scaler
# 
# Path: openlego/utils/xml_utils.py
# def param_to_xpath(param):
#     # type: (str) -> str
#     """Convert an ``OpenMDAO`` parameter name to the corresponding XML XPath.
# 
#     This function is the inverse of `xpath_to_param()`.
# 
#     Parameters
#     ----------
#         param : str
#             Valid ``OpenMDAO`` parameter name.
# 
#     Returns
#     -------
#         str
#             Corresponding XML XPath.
#     """
#     xpath = param.replace(repl_emm, repl_emm_inv)
#     xpath = xpath.replace(repl_qtm, repl_qtm_inv)
#     xpath = xpath.replace(repl_str, repl_str_inv)
#     xpath = xpath.replace(repl_dot, repl_dot_inv)
#     xpath = re_ind_inv.sub(repl_ind_inv, xpath)
#     xpath = re_atr_inv.sub(repl_atr_inv, xpath)
#     return xpath


# Path: openlego/core/b2k_solver.py
import copy
import os
import pickle
import numpy as np
import plotly
import plotly.graph_objs as go
from math import isnan as isnan
from typing import List
from openmdao.api import NonlinearBlockGS
from openmdao.core.analysis_error import AnalysisError
from openmdao.recorders.recording_iteration_stack import Recording
from openmdao.utils.general_utils import format_as_float_or_array
from openlego.utils.general_utils import str_to_valid_sys_name, unscale_value, scale_value
from openlego.utils.xml_utils import param_to_xpath

                                                if i > 0 else "..."))

        # Constraints
        print('CONSTRAINTS')
        for var_name in sorted(self.OPT_CON_VALUES.keys()):
            print(var_name)
            attrbs = self.ATTRBS_CON_VALUES[var_name]
            if attrbs['equals'] is not None:
                print('{} (== {})\n'.format(self.OPT_CON_VALUES[var_name][i][0], attrbs['equals']))
            elif attrbs['lower'] is not None or attrbs['upper'] is not None:
                print('{} (> {}, < {})\n'.format(self.OPT_CON_VALUES[var_name][i][0],
                                                 attrbs['lower'], attrbs['upper']))
            else:
                print('{} (unbounded)\n')

        # Objectives
        print('OBJECTIVE(S)')
        for var_name in sorted(self.OPT_OBJ_VALUES.keys()):
            print(var_name)
            print('{}\n'.format(self.OPT_OBJ_VALUES[var_name][i][0]))

    def _plot_history(self):
        # type: () -> None
        """Plot the results of the last B2k iteration in the browser."""
        traces_des_vars = []
        des_var_names = sorted(self.OPT_DV_VALUES.keys())
        legend_entries = [x.split('/')[-1] for x in des_var_names]
        for var_name, legend_name in zip(des_var_names, legend_entries):
            ref0s = self.REF0_VALUES[var_name]
            refs = self.REF_VALUES[var_name]

            val_opt = [float(unscale_value(val, ref0s[k], refs[k]))