0

I am trying to automatically generate lambda functions given a list of lists of strings to generate constraints for a scipy.optimize.minimize() routine. I have a list of string pairs, which I need to pass into each lambda function constraint, as so:

list = [
["parameter1", "parameter2"],
["parameter3", "parameter4"]
]

constraints = []
for pair in list:
    constraints.append( {"type":"ineq","fun": lambda p: p[param_names.index(pair[0])]-p[param_names.index(pair[1])]} )

However, when this list of constraints is passed to scipy.optimize.minimize(), the constraints are ignored. Alternatively, when I explicitly define the strings like so

cons = [
{'type':'ineq','fun': lambda p: p[param_names.index("parameter1")]-p[param_names.index("parameter2")] },
{'type':'ineq','fun': lambda p: p[param_names.index("parameter3")]-p[param_names.index("parameter4")] }
]

scipy.optimize.minimize() obeys the constraints. I believe this is a problem with how I'm defining the lambda function, namely trying to pass variables (the strings) into the lambda function, and not a problem with scipy.optimize.minimize(). I need my code to be able to parse a list of pairs of strings as above to automatically define these lambda functions and constraints, since the list can vary depending on the situation.

Is there a way to pass variables from outside the lambda function into the lambda function? Or another way I should be doing this?

1 Answers1

1

See this answer to a similar question. In your case, the problem is the use of the name pair in the lambda expression. Because of Python's late-binding closures, pair will refer to the value that it has at the time the lambda is evaluated, not the value that it had when the lambda was defined. In your code, that probably means pair will always refer to the last element in list.

A possible fix:

constraints = []
for pair in list:
    constraints.append({"type": "ineq", "fun": lambda p, pair=pair: p[param_names.index(pair[0])]-p[param_names.index(pair[1])]})

Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214