-
Notifications
You must be signed in to change notification settings - Fork 6
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
Avoid copy.deepcopy (restriction in FEniCS) #90
Comments
After trying myself, I can confirm that, after eliminating the deepcopy occurrences, errors arise when the problem is passed consecutively to several solvers. As of now, I have no suggestion on the path of action for this. |
Did you check, what exactly is internally changed when the problem is passed to a solver (resulting in problems when passing it to multiple solvers)? |
I just checked it, the problem is in the function _translate_forward_models from SciPy's solver: probeye/probeye/inference/scipy/solver.py Lines 78 to 109 in 41cf7ae
The other solvers currently inherit from the SciPy's, therefore they behave in the same way. probeye/probeye/inference/scipy/solver.py Line 109 in 41cf7ae
This is possible because in lines 88-89 the function sees that the base class from the ForwardModelHull object is DerivedModelClass: probeye/probeye/inference/scipy/solver.py Lines 88 to 89 in 41cf7ae
However, once the function is called, the forward model remains as the instance of DerivedModelClass. Here it is where deepcopy is required. At the solver level, a deepcopy of the initial problem is created (i.e. the one with a ForwardModelHull instance as forward model), therefore the original problem is not modified when the previous functions are called. In that case, every solver starts with a ForwardModelHull instance as forward model. Without the deepcopy, all the solvers share the same original problem. Only the first one will see a ForwardModelHull instance as forward model, while the others will see a DerivedModelClass. When calling A possible solution would be having different variables for the list of forward models and for their hulls in the solver level instead of overwriting the hull with the new model. I am not sure this is a good alternative, as it would mean to effectively copy the model in memory twice (plus one extra for each new solver), which can become problematic for large ones. Nevertheless, this would not prevent new issues to arise due to the manipulation of the problem. |
Not sure of the proposed option would work, since even then you would need the deep copy to create the forward model. The reason for having the hull seems that we wanted to separate the problem definition from the actual implementation that have compute capabilities, e.g. to evaluate the prior using scipy or pyro (that is solver specific). However, the forward model is IMO not part of that and the translation of the experimental data (connect_experimental_data_to_sensors) and prepare_experimental_inputs_and_outputs might just be done once (so for the first solver if the forward model is not yet the derived class). I think the original problem was that some solver (pyro) needed different interfaces (tensors instead of numpy arrays), but since pyro has been removed, this is no longer required. |
To my experience, rebuilding FW model should be OK, as the time needed for it is too small compared to solution phases. Removing deepcopy is also a simple work-around which has so far worked for me (with no error). Though, I would also prefer to be confident about this change. And to approve this change in the whole library, it looks that quite many of the tests should be revised (most likely by rebuilding FW models defined therein), because otherwise those tests would fail. |
As I've mentioned, it is not sufficient to remove the deepcopy, but to perform the additional initialization only for the first conversion. |
I just briefly looked at the problem, but I think the first two probeye/probeye/definition/experiment.py Line 40 in 41cf7ae
and also probeye/probeye/inference/solver.py Line 34 in 41cf7ae
should not result in errors. In the first instance, deepcopy only applies on data as Abbas already pointed out. But also in the second appearance the deepcopy should only apply on problem-objects that only have the forward model hulls, and not the full forward models.
As I see it, the problem is triggered by the third probeye/probeye/subroutines.py Line 1295 in 41cf7ae
and its use in the _translate_forward_models method. Maybe try to replace that third deepcopy appearance by a simple copy and keep the other two deepcopy s. All the tests pass when this is done.
|
New likelihood and correlation models with prescribed covariance Changed deepcopy to copy (see Issue BAMresearch#90)
A lot of models we practically wish to calibrate with probeye are developed in FEniCS, as it is the main simulation tool in our group. In FEniCS there is a restriction: we cannot deepcopy a FEniCS function, which is very often used in a simulator. Nevertheless, in probeye there are currently some places where the inference problem and its ingredients (mainly the forward model/simulator) are subjected to 'deepcopy'. This obviously raises failing errors as soon as there is any FEniCS function as attribute of the forward model we sub-class from probeye.ForwardModelBase. This (having FEniCS function as attribute of FW model) can certainly be avoided in simple examples of FW models, however, I find this as a major restriction in developing more involved FW models that we are going to sub-class from probeye.ForwardModelBase .
I am not sure which reasons are considered for making deepcopy of the inference problem in probeye. Maybe it has been a safe way of passing the same problem to several solvers. If so, perhaps a better approach instead of making deepcopy would be to introduce methods like 'reset_problem', such that the problem and particularly the forward simulator behind it can be returned to their original default state. Maybe this method can be considered as a must attribute of any forward simulator that a user is going to calibrate by probeye.
Edit:
Still a simple default method for such 'reset_problem' routine could be just making a deepcopy. The user can optionally provides/overwrites their own choice.
Edit-2:
There exist in total three of such copy.deepcopy operations in probeye:
probeye/probeye/definition/experiment.py
Line 40 in 41cf7ae
probeye/probeye/inference/solver.py
Line 34 in 41cf7ae
probeye/probeye/subroutines.py
Line 1295 in 41cf7ae
The first one is OK, as it regards to the data, which is in standard python formats like array, float, int, etc. However, the other two cases raise errors.
The text was updated successfully, but these errors were encountered: