working pulp
This commit is contained in:
		| @@ -81,6 +81,7 @@ def test_bellecour(client, request) :   # pylint: disable=redefined-outer-name | ||||
|             } | ||||
|         ) | ||||
|     result = response.json() | ||||
|     print(result) | ||||
|     landmarks = load_trip_landmarks(client, result['first_landmark_uuid']) | ||||
|  | ||||
|     # Get computation time | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import yaml, logging | ||||
| import numpy as np | ||||
| import pulp as pl | ||||
| from scipy.optimize import linprog | ||||
| from scipy.sparse import lil_matrix, csr_matrix | ||||
| from collections import defaultdict, deque | ||||
|  | ||||
| from ..structs.landmark import Landmark | ||||
| @@ -69,7 +70,7 @@ class Optimizer: | ||||
|             for j in range(i+1, L) : | ||||
|                 if i !=j : | ||||
|                     t = get_time(spot1.location, landmarks[j].location) | ||||
|                     A_ub[0, i*L + j] = t  + spot1.duration | ||||
|                     A_ub[0, i*L + j] = t + spot1.duration | ||||
|                     A_ub[0, j*L + i] = t + landmarks[j].duration | ||||
|  | ||||
|         # Expand 'c' to L*L for every decision variable | ||||
| @@ -255,7 +256,7 @@ class Optimizer: | ||||
|                 incr += 1 | ||||
|  | ||||
|  | ||||
|     # Prevent the use of a particular solution | ||||
|     # Prevent the use of a particular solution. TODO probably can be done faster just using resx | ||||
|     def prevent_config(self, resx): | ||||
|         """ | ||||
|         Prevent the use of a particular solution by adding constraints to the optimization. | ||||
| @@ -330,9 +331,7 @@ class Optimizer: | ||||
|             tuple[list[int], Optional[list[list[int]]]]: A tuple containing the visit order and a list of any detected circles. | ||||
|         """ | ||||
|         resx = np.round(resx).astype(np.int8)  # round all elements and cast them to int | ||||
|          | ||||
|         print(f"resx = ") | ||||
|         # for r in resx : print(r) | ||||
|  | ||||
|         N = len(resx)               # length of res | ||||
|         L = int(np.sqrt(N))         # number of landmarks. CAST INTO INT but should not be a problem because N = L**2 by def. | ||||
|  | ||||
| @@ -509,14 +508,21 @@ class Optimizer: | ||||
|  | ||||
|         # SET CONSTRAINTS FOR INEQUALITY | ||||
|         c, A_ub, b_ub = self.init_ub_time(landmarks, max_time)  # Adds the distances from each landmark to the other. | ||||
|         print("ok1") | ||||
|         self.respect_number(A_ub, b_ub, L, max_landmarks)       # Respects max number of visits (no more possible stops than landmarks). | ||||
|         print("ok2") | ||||
|         self.break_sym(A_ub, b_ub, L)                           # Breaks the 'zig-zag' symmetry. Avoids d12 and d21 but not larger cirlces. | ||||
|  | ||||
|         # SET CONSTRAINTS FOR EQUALITY | ||||
|         print("ok3") | ||||
|         A_eq, b_eq = self.init_eq_not_stay(landmarks)           # Force solution not to stay in same place | ||||
|         print("ok4") | ||||
|         self.respect_start_finish(A_eq, b_eq, L)                # Force start and finish positions | ||||
|         print("ok5") | ||||
|         self.respect_order(A_eq, b_eq, L)                       # Respect order of visit (only works when max_time is limiting factor) | ||||
|         print("ok6") | ||||
|         self.respect_user_must(A_eq, b_eq, landmarks)           # Force to do/avoid landmarks set by user. | ||||
|         print("ok7") | ||||
|  | ||||
|         self.logger.debug(f"Optimizing with {A_ub.shape[0]} + {A_eq.shape[0]} = {A_ub.shape[0] + A_eq.shape[0]} constraints.") | ||||
|  | ||||
| @@ -539,7 +545,7 @@ class Optimizer: | ||||
|             prob += (pl.lpSum([A_eq[i][j] * x[j] for j in range(L*L)]) == b_eq[i]) | ||||
|  | ||||
|         # 6. Solve the problem | ||||
|         prob.solve(pl.PULP_CBC_CMD(msg=True)) | ||||
|         prob.solve(pl.PULP_CBC_CMD(msg=False)) | ||||
|  | ||||
|         # 7. Extract Results | ||||
|         status = pl.LpStatus[prob.status] | ||||
| @@ -559,32 +565,25 @@ class Optimizer: | ||||
|  | ||||
|         i = 0 | ||||
|         timeout = 80 | ||||
|         while circles is not None and i < timeout: | ||||
|         while circles is not None : | ||||
|             i += 1 | ||||
|             # print(f"Iteration {i} of fixing circles") | ||||
|             print("ok1") | ||||
|             A, b = self.prevent_config(solution) | ||||
|             print("ok2") | ||||
|             print(f"A: {A}") | ||||
|             print(f"b: {b}") | ||||
|             try : | ||||
|                 prob += pl.lpSum([A[j] * x[j // L][j % L] for j in range(L * L)]) == b | ||||
|             except Exception as exc : | ||||
|                 self.logger.error(f'Unexpected error occured', details=exc) | ||||
|                 raise Exception from exc | ||||
|      | ||||
|             print("ok3") | ||||
|             # l, b = self.prevent_config(solution) | ||||
|             # prob += (pl.lpSum([l[j] * x[j] for j in range(L*L)]) == b) | ||||
|  | ||||
|             for circle in circles : | ||||
|                 A, b = self.prevent_circle(circle, L) | ||||
|                 prob += (pl.lpSum([A[0][j] * x[j // L][j % L] for j in range(L*L)]) == b[0]) | ||||
|                 prob += (pl.lpSum([A[1][j] * x[j // L][j % L] for j in range(L*L)]) == b[1]) | ||||
|             print("ok4") | ||||
|             prob.solve(pl.PULP_CBC_CMD(msg=True)) | ||||
|                 prob += (pl.lpSum([A[0][j] * x[j] for j in range(L*L)]) == b[0]) | ||||
|                 prob += (pl.lpSum([A[1][j] * x[j] for j in range(L*L)]) == b[1]) | ||||
|             prob.solve(pl.PULP_CBC_CMD(msg=False)) | ||||
|  | ||||
|             status = pl.LpStatus[prob.status] | ||||
|             solution = [pl.value(var) for var in x]  # The values of the decision variables (will be 0 or 1) | ||||
|  | ||||
|             if status != 'Optimal' : | ||||
|                 self.logger.error("The problem is overconstrained, no solution after {i} cycles.") | ||||
|                 raise ArithmeticError("No solution could be found. Please try again with more time or different preferences.") | ||||
|             if i == timeout : | ||||
|                 self.logger.error(f'Unexpected error after {timeout} iterations of fixing circles.') | ||||
|                 raise ArithmeticError("Solving failed because of overconstrained problem") | ||||
|  | ||||
| @@ -600,5 +599,5 @@ class Optimizer: | ||||
|         order = self.get_order(solution) | ||||
|         tour =  [landmarks[i] for i in order]  | ||||
|  | ||||
|         self.logger.debug(f"Re-optimized {i} times, score: {int(pl.value(prob.objective))}") | ||||
|         self.logger.debug(f"Re-optimized {i} times, objective value : {int(pl.value(prob.objective))}") | ||||
|         return tour | ||||
|   | ||||
		Reference in New Issue
	
	Block a user