I am using the Python library function scipy.minimize
to solve a series of linear equations with constraints, maximising the radius of a circle inscribed inside a polygon. See here for a visualization of what a circle inscribed inside a polygon is:
The constraints of the optimisation are the following: the distance between circle middlepoint with the coordinates (x[1],x[2) and every single line of the polygon has to be bigger than the radius - otherwise the circle radius would reach outside the polygon and the circle would no longer be inscribed.
These constraints are formulated through the following lambda functions, one function for each side of the polygon (a triangle, in our example):
# all of these functions have to remain non-negative
constraint1 = lambda x: distance_to_line((x[1],x[2]),polygon_points[0],polygon_points[1]) - x[0]
constraint2 = lambda x: distance_to_line((x[1],x[2]),polygon_points[1],polygon_points[2]) - x[0]
constraint3 = lambda x: distance_to_line((x[1],x[2]),polygon_points[2],polygon_points[3]) - x[0]
The variables here are x[0] for the circle radius and x[1], x[2] for the coordinates of the circle middlepoint.
variables = [0, 0, 0]
The objective function is the opposite of x[0], which is the circle radius:
def objective (x):
return -(x[0])
Feeding these components into the minimise function gives correct results, the program works like this and result.x[0] prints the correct radius:
constraints = [{'type': 'ineq', 'fun': constraint1},{'type': 'ineq', 'fun': constraint2},{'type': 'ineq', 'fun': constraint3}]
result = minimize(objective, variables, constraints=constraints)
print("Maximum radius: " + str(result.x[0]))
So far, so good. But this is where a problem arises. As you might have noticed, it makes sense to generate the constraint functions through list comprehension, so a potentially infinite number of polygon lines can be processed.
all_constraints = [lambda x: distance_to_line((x[1],x[2]),polygon_points[i],polygon_points[i+1]) -x[0] for i in range (0,3)]
But scipy.minimize no longer works if I feed it these three list comprehension-generated lambda functions instead of the manually written ones:
constraints = []
for function in all_constraints :
constraints.append({'type': 'ineq', 'fun': function})
Instead, I get various error messages in result.message like "Singular matrix E in LSQ subproblem" or "Inequality constraints incompatible".
This confuses me greatly, because the functions generated by list comprehension and those written manually at the start should be completely equivalent in content and results.
Are all_constraints really equivalent to the three manually written functions above, or am I making a mistake somewhere?