Search code examples
pythonscipy-optimize

Optimizing a sequence with simulated dual annealign from Scipy


I'd like to optimize a sequence of 2 values, where each value has its own bound using simulated dual annealing from scipy:

Here's an example of sequence:

self.sequence_length = 10 
        

self.action_space = [(Bounds(lb=np.pi/12, ub=5*np.pi/9), Bounds(lb=75.0, ub=200.0))] * self.sequence_length

Here's an example of output:

[((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0)), ((0.2617993877991494, 1.7453292519943295), (75.0, 200.0))]

As such, each tuple of the sequence has 2 values with its own bounds, and the goal is optimize the whole sequence:

result = dual_annealing(self.func, initial_temp=10000, bounds=self.action_space, maxfun=1000)

However, the following error arises:

Traceback (most recent call last):
  File "main.py", line 98, in <module>
    obj = Sim()
  File "main.py", line 92, in __init__
    result = dual_annealing(self.generate_sequence, initial_temp=10000, bounds=self.action_space, maxfun=1000)
  File "/home/user/miniconda3/envs/sim/lib/python3.8/site-packages/scipy/optimize/_dual_annealing.py", line 639, in dual_annealing
    if (np.any(np.isinf(lower)) or np.any(np.isinf(upper)) or np.any(
TypeError: ufunc 'isinf' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Could someone come with a solution for that?


Solution

  • The problem is that dual_annealing expects a single Bounds object with lower and upper bounds for all variables, not a list of Bounds objects. You can solve this problem by creating a single Bounds object with bounds for all variables.

    Try this snippet of code:

    self.sequence_length = 10 
    
    lb = [np.pi/12, 75.0] * self.sequence_length
    ub = [5*np.pi/9, 200.0] * self.sequence_length
    
    self.action_space = Bounds(lb=lb, ub=ub)
    
    result = dual_annealing(self.func, initial_temp=10000, bounds=self.action_space, maxfun=1000)