-
Notifications
You must be signed in to change notification settings - Fork 1
Refactor in to library - part I #64
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
Conversation
…keys in config settings
…ts, without robustness
…nd scores from dict to dataframe, broken tests
…DTool into refactor_in_to_library
kapil-agnihotri
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still reviewing the PR but here are some more comments.
| validate_configuration( | ||
| input_matrix=self.input_matrix, | ||
| polarity=self.polarity, | ||
| weights=self.weights, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think same applies to all the parameters. You have already used them in the code but validating them now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand, this is one of the first blocks of ProMCDA.py, this validation is happening just before any other processes.
If you refer to the block just before this one, the logic and order of these two blocks are consistent with the needed checks and processing of data.
I'd leave it as it is.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two previous steps are necessary to validate_configuration.
Example: if the input matrix has a column with no information, this column is dropped in check_input_matrix. The weights and polarities are consequently shortened in process_indicators_and_weights. Only then can we validate the entire configuration settings, for example, estimate the number of indicators in the case of robustness analysis in validate_configuration.
This logic and all the controls could be rewritten more organically and clearly. I leave this improvement to a later version of the library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think then this is a potential comment for a follow up ticket?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still in review but here are some more comments.
kapil-agnihotri
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am finished with the review.
| all_weights_score_means_normalized, all_weights_score_stds_normalized = \ | ||
| compute_scores_for_all_random_weights(self.normalized_values_without_robustness, norm_weights, | ||
| aggregation_method) | ||
| self.all_weights_score_means = all_weights_score_means |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to create local variable just to reassign them to member variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assigning these variables to self. is intentional because it makes them accessible throughout the class instance, beyond the scope of the current method. Without this, the variables would be local and not available to other methods or after initialization. So this assignment is necessary for maintaining the state within the class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mentioned about the local variables and not self variables. What I meant you can do is:
self.all_weights_score_means, self.all_weights_score_stds, \
self.all_weights_score_means_normalized, self.all_weights_score_stds_normalized = \
compute_scores_for_all_random_weights(self.normalized_values_without_robustness, norm_weights,
aggregation_method)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is still pending :(. Please assign self.___ variables directly instead of using intermediate variable.
…DTool into refactor_in_to_library
kapil-agnihotri
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that a lot of comments were unaddressed (most of them were from collapsable messages). Can you please address or reject them however you feel them fit? Few of them also corresponds to some logic.
Some comments were resolved without any changes so I have unresolved them.
I have also added some comments on your new logic.
promcda/models/ProMCDA.py
Outdated
| if not isinstance(robustness, RobustnessAnalysisType): | ||
| raise TypeError(f"'robustness' must be of type RobustnessAnalysisType, got {type(robustness).__name__}") | ||
|
|
||
| if self.weights is None and RobustnessAnalysisType.INDICATORS.value is not "indicators": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if I missed this before but I doubt that condition RobustnessAnalysisType.INDICATORS.value is not "indicators" would ever fail.
You are comparing enum value to a string, this would always validate to false, i.e. indicators != indicators.
| validate_configuration( | ||
| input_matrix=self.input_matrix, | ||
| polarity=self.polarity, | ||
| weights=self.weights, |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
promcda/models/ProMCDA.py
Outdated
| # Apply aggregation in the different configuration settings | ||
| # NO UNCERTAINTY ON INDICATORS AND WEIGHTS | ||
| if not self.robustness_indicators and not self.robustness_weights and not self.robustness_single_weights: | ||
| if (not self.robustness == RobustnessAnalysisType.INDICATORS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not simply check for None instead of checking for != for all the other values of enum? If I understand correctly then here you are not checking for individual values but just for a single value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any update here? Looks like this was missed.
promcda/models/ProMCDA.py
Outdated
|
|
||
| # NO UNCERTAINTY ON INDICATORS, ALL RANDOMLY SAMPLED WEIGHTS (MCDA runs num_samples times) | ||
| elif self.robustness_weights and not self.robustness_single_weights and not self.robustness_indicators: | ||
| elif (self.robustness == RobustnessAnalysisType.ALL_WEIGHTS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can self.robustness have 3 different values at a same time? If not then why do you check for all the values? i would just check for self.robustness == RobustnessAnalysisType.ALL_WEIGHTS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any update here?
promcda/models/ProMCDA.py
Outdated
|
|
||
| # NO UNCERTAINTY ON INDICATORS, ONE SINGLE RANDOM WEIGHT AT TIME | ||
| elif self.robustness_single_weights and not self.robustness_weights and not self.robustness_indicators: | ||
| elif (self.robustness == RobustnessAnalysisType.SINGLE_WEIGHTS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as before Can self.robustness have 3 different values at a same time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
promcda/models/ProMCDA.py
Outdated
|
|
||
| # UNCERTAINTY ON INDICATORS, NO UNCERTAINTY ON WEIGHTS | ||
| elif self.robustness_indicators and not self.robustness_weights and not self.robustness_single_weights: | ||
| elif (self.robustness == RobustnessAnalysisType.INDICATORS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as before Can self.robustness have 3 different values at a same time?
| print(f"MCDA ranks are retrieved") | ||
|
|
||
| if not any([self.robustness_weights, self.robustness_indicators, self.robustness_single_weights]): | ||
| if not any([self.robustness == RobustnessAnalysisType.ALL_WEIGHTS, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just check for None instead of all 3?
README.md
Outdated
| Together, these examples show both the mechanics of using the library and the applicability of its concepts. | ||
|
|
||
| In particular, `demo_in_notebook` contains: | ||
| - Two examples of setups for instatiating the ProMCDA object: one with a dataset without uncertainties and one with a dataset with uncertainties. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see only python notebook in demo_in_notebook folder. But you mentioned that there are two examples setups contained in demo_in_notebook.
If they are created within notebook then it would be great mention it here because you are referring to the folder instead of notebook. Otherwise someone might search for input files in the folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are created in the notebook, at the beginning. I edit the README.
| weights: Optional[list] = None, | ||
| robustness_weights: Optional[bool] = False, | ||
| robustness_single_weights: Optional[bool] = False, robustness_indicators: Optional[bool] = False, | ||
| robustness: RobustnessAnalysisType = RobustnessAnalysisType.NONE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the change to enum. It would also be great to update docs for this method as they still refer to old implementation with combination of robustness and weights.
promcda/models/ProMCDA.py
Outdated
| - The input_matrix should contain the alternatives as rows and the criteria as columns. | ||
| - If weights are not provided, they are set to 0.5 for each criterion. | ||
| - If robustness_weights is enabled, the robustness_single_weights should be disabled, and viceversa. | ||
| - If robustness_indicators is enabled, the robustness on weights should be disabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the change. Can you please also update docs for this method.
promcda/models/ProMCDA.py
Outdated
| if not isinstance(robustness, RobustnessAnalysisType): | ||
| raise TypeError(f"'robustness' must be of type RobustnessAnalysisType, got {type(robustness).__name__}") | ||
|
|
||
| if self.weights is None and RobustnessAnalysisType.INDICATORS.value != "indicators": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this logic still needs to be corrected. Let me explain what you are doing here. You are trying to compare enum with a string.
Your enum RobustnessAnalysisType.INDICATORS.value will give you value indicators and this is compared with negation to indicators. i.e., indicators != indicators.
What you might want to do here could be robustness.value != indicators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You were probably referring to a previous commit here. The check here is already of the kind: self.robustness != RobustnessAnalysisType.INDICATORS, that is correct and tested.
| validate_configuration( | ||
| input_matrix=self.input_matrix, | ||
| polarity=self.polarity, | ||
| weights=self.weights, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think then this is a potential comment for a follow up ticket?
promcda/models/ProMCDA.py
Outdated
| # Apply aggregation in the different configuration settings | ||
| # NO UNCERTAINTY ON INDICATORS AND WEIGHTS | ||
| if not self.robustness_indicators and not self.robustness_weights and not self.robustness_single_weights: | ||
| if (not self.robustness == RobustnessAnalysisType.INDICATORS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any update here? Looks like this was missed.
promcda/models/ProMCDA.py
Outdated
|
|
||
| # NO UNCERTAINTY ON INDICATORS, ALL RANDOMLY SAMPLED WEIGHTS (MCDA runs num_samples times) | ||
| elif self.robustness_weights and not self.robustness_single_weights and not self.robustness_indicators: | ||
| elif (self.robustness == RobustnessAnalysisType.ALL_WEIGHTS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any update here?
| all_weights_score_means_normalized, all_weights_score_stds_normalized = \ | ||
| compute_scores_for_all_random_weights(self.normalized_values_without_robustness, norm_weights, | ||
| aggregation_method) | ||
| self.all_weights_score_means = all_weights_score_means |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is still pending :(. Please assign self.___ variables directly instead of using intermediate variable.
promcda/models/ProMCDA.py
Outdated
|
|
||
| # NO UNCERTAINTY ON INDICATORS, ONE SINGLE RANDOM WEIGHT AT TIME | ||
| elif self.robustness_single_weights and not self.robustness_weights and not self.robustness_indicators: | ||
| elif (self.robustness == RobustnessAnalysisType.SINGLE_WEIGHTS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
| return polarity, norm_fixed_weights, None, None | ||
| # Return None for norm_random_weights and rand_weight_per_indicator | ||
| else: | ||
| output_weights = handle_robustness_weights(mc_runs, num_indicators, robustness_weights, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if you want then you can further improve it as (as per my initial suggestion)
norm_random_weights, rand_weight_per_indicator = handle_robustness_weights(mc_runs, num_indicators, robustness)
|
@kapil-agnihotri Please approve. |
I finally came to have a good working basis of ProMCDA refactored into a library. In this first part, you can find the following major improvements:
It's a good moment for you to start reviewing the changes. In particular, I wish that:
In the meantime, I will continue the refactoring; in particular, we still need to:
Future, optional improvements:
or stored as an internal attribute so tests remain flexible