21
21
__all__ = ["MonteCarlo" , "AnnealingSchedule" , "GlobalOptimType" ]
22
22
23
23
import warnings
24
+ from types import MethodType
25
+
24
26
try :
25
27
import ipywidgets as widgets
26
28
except ImportError :
27
29
widgets = None
28
- from pyobjcryst ._pyobjcryst import MonteCarlo as MonteCarlo_orig , AnnealingSchedule , GlobalOptimType
30
+ from pyobjcryst ._pyobjcryst import MonteCarlo as MonteCarlo_orig , AnnealingSchedule , \
31
+ GlobalOptimType , OptimizationObjRegistry
29
32
from .refinableobj import *
30
33
31
34
32
35
class MonteCarlo (MonteCarlo_orig ):
33
36
34
37
def Optimize (self , nb_step : int , final_cost = 0 , max_time = - 1 ):
35
38
self ._fix_parameters_for_global_optim ()
36
- super ().Optimize (int (nb_step ), True , final_cost , max_time )
39
+ if type (self ) == MonteCarlo_orig :
40
+ self ._Optimize (int (nb_step ), True , final_cost , max_time )
41
+ else :
42
+ super ().Optimize (int (nb_step ), True , final_cost , max_time )
37
43
38
44
def MultiRunOptimize (self , nb_run : int , nb_step : int , final_cost = 0 , max_time = - 1 ):
39
45
self ._fix_parameters_for_global_optim ()
40
- super ().MultiRunOptimize (int (nb_run ), int (nb_step ), True , final_cost , max_time )
46
+ if type (self ) == MonteCarlo_orig :
47
+ self ._MultiRunOptimize (int (nb_run ), int (nb_step ), True , final_cost , max_time )
48
+ else :
49
+ super ().MultiRunOptimize (int (nb_run ), int (nb_step ), True , final_cost , max_time )
41
50
42
51
def RunSimulatedAnnealing (self , nb_step : int , final_cost = 0 , max_time = - 1 ):
43
52
self ._fix_parameters_for_global_optim ()
44
- super ().RunSimulatedAnnealing (int (nb_step ), True , final_cost , max_time )
53
+ if type (self ) == MonteCarlo_orig :
54
+ self ._RunSimulatedAnnealing (int (nb_step ), True , final_cost , max_time )
55
+ else :
56
+ super ().RunSimulatedAnnealing (int (nb_step ), True , final_cost , max_time )
45
57
46
58
def RunParallelTempering (self , nb_step : int , final_cost = 0 , max_time = - 1 ):
47
59
self ._fix_parameters_for_global_optim ()
48
- super ().RunParallelTempering (int (nb_step ), True , final_cost , max_time )
60
+ if type (self ) == MonteCarlo_orig :
61
+ self ._RunParallelTempering (int (nb_step ), True , final_cost , max_time )
62
+ else :
63
+ super ().RunParallelTempering (int (nb_step ), True , final_cost , max_time )
49
64
50
65
def _fix_parameters_for_global_optim (self ):
51
66
# Fix parameters that should not be optimised in a MonterCarlo run
@@ -58,7 +73,7 @@ def _fix_parameters_for_global_optim(self):
58
73
59
74
def widget (self ):
60
75
"""
61
- Display a simple widget for this MonteCarloObj , which only updates the current
76
+ Display a simple widget for this MonteCarlo , which only updates the current
62
77
cost (log-likelihood). Requires ipywidgets
63
78
"""
64
79
if widgets is None :
@@ -101,3 +116,49 @@ def _widget_update(self):
101
116
else :
102
117
self ._widget_llk .value = "LLK=%12.2f " % self .llk
103
118
self ._widget_llk .layout .width = '%dem' % len (self ._widget_llk .value )
119
+
120
+
121
+ def wrap_boost_montecarlo (c : MonteCarlo ):
122
+ """
123
+ This function is used to wrap a C++ Object by adding the python methods to it.
124
+
125
+ :param c: the C++ created object to which the python function must be added.
126
+ """
127
+ if 'widget' not in dir (c ):
128
+ for func in ['Optimize' , 'MultiRunOptimize' , 'RunSimulatedAnnealing' , 'RunParallelTempering' ]:
129
+ # We keep access to the original functions... Yes, it's a kludge...
130
+ exec ("c._%s = c.%s" % (func , func ))
131
+ for func in ['Optimize' , 'MultiRunOptimize' , 'RunSimulatedAnnealing' , 'RunParallelTempering' ,
132
+ '_fix_parameters_for_global_optim' , 'widget' , 'UpdateDisplay' ,
133
+ 'disable_display_update' , 'enable_display_update' , '_widget_update' ]:
134
+ exec ("c.%s = MethodType(MonteCarlo.%s, c)" % (func , func ))
135
+
136
+
137
+ class OptimizationObjRegistryWrapper (OptimizationObjRegistry ):
138
+ """
139
+ Wrapper class with a GetObj() method which can correctly wrap C++ objects with
140
+ the python methods. This is only needed when the objects have been created
141
+ from C++, e.g. when loading an XML file.
142
+ """
143
+
144
+ def GetObj (self , i ):
145
+ o = self ._GetObj (i )
146
+ # TODO
147
+ print ("Casting OptimizationObj to MonteCarlo and wrapping.." )
148
+ # We get the object as an OptimizationObj, which prevents access to some functions
149
+ # So we use this function to cast to a MonteCarloObj
150
+ o = self ._getObjCastMonteCarlo (i )
151
+ wrap_boost_montecarlo (o )
152
+ return o
153
+
154
+
155
+ def wrap_boost_optimizationobjregistry (o ):
156
+ """
157
+ This function is used to wrap a C++ Object by adding the python methods to it.
158
+
159
+ :param c: the C++ created object to which the python function must be added.
160
+ """
161
+ # TODO: moving the original function is not very pretty. Is there a better way ?
162
+ if '_GetObj' not in dir (o ):
163
+ o ._GetObj = o .GetObj
164
+ o .GetObj = MethodType (OptimizationObjRegistryWrapper .GetObj , o )
0 commit comments