Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creation of the LEGOProblem class #13

Merged
merged 12 commits into from
Aug 7, 2018

Conversation

imcovangent
Copy link
Contributor

This pull request introduces a new class called LEGOProblem. This is a subclass of the OpenMDAO Problem class which:

  • provides the ability to instantiate a Problem object based on a CMDOWS file with fully configured LEGOModel, converger groups and drivers for the OpenMDAO object.
  • includes some helpful utilities to automatically configure a case reader and read out (and optionally print out) its main results in a dictionary object based on the type of run that was executed (MDA, DOE, MDO).

All test case in the OpenLEGO test suite have also been updated and validated using the new LEGOProblem class.

imcovangent added 9 commits August 2, 2018 11:33
…st all KADMOS architectures (MDA, DOE, monolithic MDO) are now supported.

Included some new utility functions.
Added documentation to problem.py file.
Added automatic case reader and printing functionality.
Added many new CMDOWS test files for the test suite.
Updated sellar_competences_test, still to do other tests.
# Conflicts:
#	openlego/test_suite/test_examples/sellar_competences/sellar_competences_test.py
Changed print_results() method to collect_results() method with optional printing and return of results dictionary.
Added utility function to print with Boolean (print_optional(string, print_in_log)), alternative would be to use a logger.
Added utility function to clean a directory based on a filter (clean_dir_filtered(dir, filters))
Added utility function to expand a dictionary safely (add_or_append_dict_entry(main_dict, main_key, sub_key, value)
Small updates to other test files.
Copy link
Owner

@daniel-de-vries daniel-de-vries left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall: really great work! There are a few small things I want to address. Please have a look.

class LEGOProblem(Problem):
"""Specialized OpenMDAO Problem class representing the problem specified by a CMDOWS file.

# TODO: Daniel: is this also true here?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is also true here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then we keep the comment.

An important note about this class in the context of OpenMDAO is that the aggregation pattern of the root Problem
class has is changed into a stronger composition pattern. This is because this class directly
controls the creation and assembly of this class by making use of Python's @property decorator. It is not possible,
nor should it be attempted, to manually inject a different instance of Problem in place of these, because the
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these -> this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

print_optional('Optimum found!', print_in_log)
else:
print_optional('Driver finished!', print_in_log)
print_optional('\nPrinting case numbers: {}'.format(num_cases, cases_to_collect), print_in_log)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many arguments for the string format.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted! :)

def driver_type(self):
# type: () -> Union[str, None]
""":obj:`str`: Type of driver as string."""
assert len(self.drivers['optimizers']) + len(self.drivers['does']) <= 1, \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy is used on this repo to help ensure good code quality. One of the flags it threw was that it is better to use a construction like

if condition:
    raise AssertionError('message')

instead of assert condition, 'message', because the protections these assertions offer are removed when the code is compiled. Furthermore, it is considered general bad practice. So please change this and the other assertions to a if-then construction.

Note that this does not apply to the assertion methods used in TestCases. There it is warranted by the unittest framework.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, all assert code lines have been adjusted as suggested.

results : dict of dicts
Dictionary containing the results that were collected
"""
assert os.path.isfile(self.case_reader_path), 'Could not find the case reader file {}.'\
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment about assertions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted as suggested.

.format(self.case_reader_path)
assert isinstance(cases_to_collect, (str, list)), 'cases_to_print must be of type str or list.'
if isinstance(cases_to_collect, str):
assert cases_to_collect in ['default', 'all', 'last'], 'Invalid cases_to_print string value provided.'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment about assertions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted as suggested.

@@ -103,6 +106,37 @@ def get_uid_search_xpath(uid):
return './/*[@uID="' + uid + '"]'


def get_opt_setting_safe(opt_elem, setting, default, expected_type='str'):
# TODO: Add docstring and type
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please indeed add the docstring and type hint

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!



def get_doe_setting_safe(doe_elem, setting, default, expected_type='str', doe_method=None, required_for_doe_methods=None):
# TODO: Add docstring and type
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please indeed add the docstring and type hint

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

raise IOError('expected_type "{}" is not supported in this function.'.format(new_type))


def clean_dir_filtered(dir, filters):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dir is a built-in parameter in Python. Shadowing these is considered bad practice, so please change this local variable name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to dr (also file has been changed to f).

# type: (path, List[str]) -> None
"""Removes files in a directory that contain the strings provided in the filter."""
for file in os.listdir(dir):
for filter in filters:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter is a built-in parameter in Python. Shadowing these is considered bad practice, so please change this local variable name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to fltr

@imcovangent
Copy link
Contributor Author

All requested changes have been addressed. Ready to pull, I hope! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants