I have read this post
PuLP very slow when adding many constraints
and still remain oblivious to a solution.
def choose_lines_to_satisfy_image(lines_list_high_res, image_low_res, lines_to_low_res_matrix, allowed_diff_between_targe_pixel_and_result):
problem = LpProblem("Solving Lines Discretely", LpMinimize) # minimize or maximize doesn't matter
problem += 0 # objective function must be added first. it is zero, because we are only looking for a feasable solution. nothing to optimize.
number_of_lines = len(lines_list_high_res)
lines_names_list = []
for i in range(len(lines_list_high_res)):
line_name = str(i)
lines_names_list.append(line_name)
print("len(lines_names_list)")
print(len(lines_names_list))
line_variables = LpVariable.dicts("line", lines_names_list, lowBound=0, upBound=1, cat=LpInteger)
# print('dicts = ')
# print(line_variables)#can't do this. python hangs. want it? spit it to a log file.
num_of_lines, num_of_low_res_pixels = lines_to_low_res_matrix.shape
if len(lines_list_high_res) != num_of_lines:
print("oh crap")
return
# add constraints
# each constraint is: |pixel-expected-value - pixel-actual-value| < allowed_diff_between_targe_pixel_and_result
# which translates to 2 constraints:
# 1) sum(lines coefficients through pixel) < pixel-expected-value + allowed_diff_between_targe_pixel_and_result
# 2) sum(lines coefficients through pixel) < pixel-expected-value - allowed_diff_between_targe_pixel_and_result
for pixel_low_res_ind in range(num_of_low_res_pixels):
print("setting constraints for low res pixel # ", pixel_low_res_ind, " out of ", num_of_low_res_pixels)
pixel_low_res_x, pixel_low_res_y = ind2sub(image_low_res.shape, pixel_low_res_ind)
constraint_1_name = "Constraint 1 for pixel " + str(pixel_low_res_ind)
constraint_2_name = "Constraint 2 for pixel " + str(pixel_low_res_ind)
#TODO this should be done for only the lines that pass through the pixel. how shall I know which ones?
constraint_predicate_1 = lpSum([line_variables[str(j)] * lines_to_low_res_matrix[j][pixel_low_res_ind] for j in range(num_of_lines)]) \
<= image_low_res[pixel_low_res_x][pixel_low_res_y] + allowed_diff_between_targe_pixel_and_result
#TODO this should be done for only the lines that pass through the pixel. how shall I know which ones?
constraint_predicate_2 = lpSum([line_variables[str(j)] * lines_to_low_res_matrix[j][pixel_low_res_ind] for j in range(num_of_lines)]) \
>= image_low_res[pixel_low_res_x][pixel_low_res_y] - allowed_diff_between_targe_pixel_and_result
problem += constraint_predicate_1, constraint_1_name
problem += constraint_predicate_2, constraint_2_name
#TODO make this path relative
print("writing problem to file")
problem.writeLP("D:/git/stav/python/threadart/linear_problems/problem.lp")
print("solving problem")
problem.solve(PULP_CBC_CMD(msg=0))
I have used lpSum and still the creation of constraints takes over an hour. Also, there is no indication of the progression of the solution.
I have 4096 constraints, each containing about 8500 variables. They are sparse to some extent, but I did not mention that anywhere (Should I?)
Please tell me how I can speed up the problem creation process to something more realistic.
I wouldn't mind creating some file the Pulp would read myself (i noticed there is a problem.write () method, but no problem.read())
Thanks!