e2nIEE / pandapower

Convenient Power System Modelling and Analysis based on PYPOWER and pandas
https://www.pandapower.org
Other
848 stars 478 forks source link

nets_equal(): enable comparing objects in DataFrames such as controller objects #1316

Closed SteffenMeinecke closed 3 months ago

SteffenMeinecke commented 3 years ago

With 30f806b9703e2e83808fe181d5a7ad2a1f350708 a significant improvement of nets_equal() is available. A still open issue is to compare objects in DataFrames such as the column net.controller.object. Currently, this is skipped. A possibile way to solve this is to use the string serialization functionality which is used with to_json(). Maybe @rbolgaryn you can have a look here?

SteffenMeinecke commented 3 years ago

The functionality of comparing controller objects with each other could also be used to write a routine which updates the controller_object.index value. This value can be corrupted if functions or the user changes the (order and) index of the dataframe net.controller.

SteffenMeinecke commented 2 years ago

simple rudimentary script to check the functionality:

import pandapower as pp
import pandapower.control as ct
import pandapower.networks as nw

net1 = nw.case9()
net2 = nw.case9()
net3 = nw.case9()
ct.ConstControl(net1, "load", "p_mw", 3)
ct.ConstControl(net2, "load", "p_mw", 3)
ct.ConstControl(net3, "load", "p_mw", 2)

assert pp.nets_equal(net1, net2)
eq = pp.nets_equal(net1, net3)  # correct: eq is False; at the moment: Warning that object columns are skipped and eq is True
rbolgaryn commented 2 years ago

As a workaround for now sure, but a better way to do it would be in my opinion the following:

1) drop the method "equals" from JSONSerializableClass 2) define the method __eq__ in JSONSerializableClass that raises a NotImplementedError 3) all the classes that inherit from JSONSerializableClass implement their own comparisons depending on what is reasonable

This way, every class (and the developer of that class) is responsible for the correct behavior that makes sense in that particular case. For example, ConstControl implements comparison by checking the attributes element, profile_name, element_index, data_source. DataSource implements comparison by checking the underlying DataFrame or .csv file etc. Then instead of using netsequal(net1, net2), one could easily write net1==net2, which also falls back on the \_eq__ implementations of the involved pandapower objects.

This way, the code becomes clearer and the usage of == is supported. To check if the objects are the same in memory, one could still use "is".

Thoughts?

dlohmeier commented 2 years ago

This might get really tough to implement, but could be worth a try. Maybe we should collect data types / classes that need special treatment in this function. I would like to start with nx graphs, as they cannot be compared easily (I implemented the comparison with the graphs_equal function, but it does not support ==)

SteffenMeinecke commented 2 years ago

From my point of view, an implementation that allows to compare objects within net dataframes, according to their __eq__ functionality, would be an important step. Enabling the very nice notation net1 == net2 would not be that important to me, because naming the function nets_equal() is not much more effort and the function itself has to stay anyway (for cases that users only want to compare only_results or without_results, for example).

Translated with www.DeepL.com/Translator (free version)

rbolgaryn commented 2 years ago

I hope that with the __eq approach, the comparison implementations will work in a chain, so to say, so that if a dataframe has an object with __eq implemented, then comparing them will work out of the box. But this needs to be tested first to see if it is a correct assumption. If it works as I imagine, it will be convenient. Also, with raising NotImplementedError, all the classes that need this implementation will be easy to find.

SteffenMeinecke commented 3 months ago

above minimal example works now.