4

I am running an optimisation problem using the module scipy.optimize.differential_evolution. The code I wrote is quite complex and I will try to summarise the difficulties I have:

  1. the objective function is calculated with an external numerical model (i.e. I am not optimising an analytical function). To do that I created a specific function that runs the model and another one to post process the results.
  2. I am constraining my problem with some constraints. The constraints are not constraining the actual parameters of the problem but for some dependent variables that can be obtained only at the end of the simulation of my external numerical model. Each constraint was defined with a separate function

The problem with 2. is that the external model might be run twice for the same set of parameters: the first time to calculate the objective function and the second time to calculate the dependent variables to be assessed for the constraints. To avoid that and speed up my code I created a global dictionary were I save the results of my dependent variables for each set of parameters (as a look up table) every time the external model is called. This will prevent the function that assesses the constraints to run the model again for the same set of parameters.

This works very well when I use a single CPU optimisation. However, it is my understanding that the function differential_evolution allows also multiprocessing by setting an appropriate value to the option "workers" (see here https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.differential_evolution.html#r108fc14fa019-1). My problems is that I have no idea how to update a global/shared variable when I enable the multiprocessing capability.

The webpage above states: "If workers is an int the population is subdivided into workers sections and evaluated in parallel (uses multiprocessing.Pool) [...]"

So I deduced that I have to find a way to modify a shared variable when multiprocessing.pool is used. In this regard I found these solutions:

Shared variable in python's multiprocessing

multiprocessing.Pool with a global variable

Why multiprocessing.Pool cannot change global variable?

Python sharing a dictionary between parallel processes

I think the last one is appropriate for my case. However, I am not sure how I have to set up my code and the workers option of the differential_evolution function. Any help will be appreciated.

My code is something like:

def run_external_model(q):
    global dict_obj, dict_dep_var 
    ....
    obj, dep_var = post_process_model(q)
    dict_var_dep[str(q)] = dep_var
    dict_obj[str(q)] = obj

def obj(q):
    global dict_obj
    if str(q) not in list(dict_obj.keys()):
        run_external_model(q)
    return dict_obj[str(q)]

def constraint(q):
    global dict_dep_var
    if str(q) not in list(dict_dep_var.keys()):
        run_external_model(q)
    return dict_dep_var[str(q)]


dict_obj = {}
dict_dep_var = {}

nlcs = scipy.optimize.NonLinearConstraint(constraint, 0., np.inf)

q0 = np.array([q1, .... , qn])
b = np.array([(0, 100.)] * len(q0))

solution = scipy.optimize.differential_evolution(objective, bounds=(b), constraints=(nlcs), seed=1)

The code above works with a single core. I am trying a solution to share the dictionaries dict_obj and dict_dep_var

Giovanni
  • 41
  • 2

0 Answers0