fixed circular symmetry
This commit is contained in:
		| @@ -40,9 +40,6 @@ def untangle2(resx: list) : | |||||||
|  |  | ||||||
|     return order |     return order | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Convert the result (edges from j to k like d_25 = edge between vertex 2 and vertex 5) into the list of indices corresponding to the landmarks | # Convert the result (edges from j to k like d_25 = edge between vertex 2 and vertex 5) into the list of indices corresponding to the landmarks | ||||||
| def untangle(resx: list) : | def untangle(resx: list) : | ||||||
|     N = len(resx)                # length of res |     N = len(resx)                # length of res | ||||||
| @@ -102,7 +99,49 @@ def print_res(res: list, landmarks: list, P) : | |||||||
|     steps = path_length(P, abs(res.x)) |     steps = path_length(P, abs(res.x)) | ||||||
|     print("\nSteps walked : " + str(steps)) |     print("\nSteps walked : " + str(steps)) | ||||||
|  |  | ||||||
| # Constraint to not have d14 and d41 simultaneously |  | ||||||
|  | # Checks for cases of circular symmetry in the result | ||||||
|  | def has_circle(resx: list) : | ||||||
|  |     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. | ||||||
|  |     n_edges = resx.sum()      # number of edges | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     nonzeroind = np.nonzero(resx)[0] # the return is a little funny so I use the [0] | ||||||
|  |  | ||||||
|  |     nonzero_tup = np.unravel_index(nonzeroind, (L,L)) | ||||||
|  |  | ||||||
|  |     indx = nonzero_tup[0].tolist() | ||||||
|  |     indy = nonzero_tup[1].tolist() | ||||||
|  |      | ||||||
|  |  | ||||||
|  |     verts = [] | ||||||
|  |  | ||||||
|  |     for i, x in enumerate(indx) : | ||||||
|  |         verts.append((x, indy[i])) | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     for vert in verts : | ||||||
|  |         visited = [] | ||||||
|  |         visited.append(vert) | ||||||
|  |  | ||||||
|  |         while len(visited) < n_edges + 1 : | ||||||
|  |  | ||||||
|  |             try :  | ||||||
|  |                 ind = indx.index(vert[1]) | ||||||
|  |  | ||||||
|  |                 vert = (indx[ind], indy[ind]) | ||||||
|  |  | ||||||
|  |                 if vert in visited : | ||||||
|  |                     return visited | ||||||
|  |                 else : | ||||||
|  |                     visited.append(vert) | ||||||
|  |             except : | ||||||
|  |                 break | ||||||
|  |  | ||||||
|  |     return [] | ||||||
|  |  | ||||||
|  | # Constraint to not have d14 and d41 simultaneously. Does not prevent circular symmetry with more elements | ||||||
| def break_sym(landmarks, A_ub, b_ub): | def break_sym(landmarks, A_ub, b_ub): | ||||||
|     L = len(landmarks) |     L = len(landmarks) | ||||||
|     upper_ind = np.triu_indices(L,0,L) |     upper_ind = np.triu_indices(L,0,L) | ||||||
| @@ -125,6 +164,26 @@ def break_sym(landmarks, A_ub, b_ub): | |||||||
|  |  | ||||||
|     return A_ub, b_ub |     return A_ub, b_ub | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def prevent_circle(landmarks, A_ub, b_ub, circle) : | ||||||
|  |     N = len(landmarks) | ||||||
|  |     l = [0]*N*N | ||||||
|  |  | ||||||
|  |     for index in circle : | ||||||
|  |         x = index[0] | ||||||
|  |         y = index[1] | ||||||
|  |         l[x*N+y] = 1 | ||||||
|  |  | ||||||
|  |     A_ub = np.vstack((A_ub,l)) | ||||||
|  |     b_ub.append(len(circle)-1) | ||||||
|  |  | ||||||
|  |     """print("\n\nPREVENT CIRCLE") | ||||||
|  |     for i in range(7): | ||||||
|  |         print(l[i*7:i*7+7]) | ||||||
|  |     print("\n")""" | ||||||
|  |  | ||||||
|  |     return A_ub, b_ub | ||||||
|  |  | ||||||
| # Constraint to respect max number of travels | # Constraint to respect max number of travels | ||||||
| def respect_number(landmarks, A_ub, b_ub): | def respect_number(landmarks, A_ub, b_ub): | ||||||
|     h = [] |     h = [] | ||||||
| @@ -152,9 +211,9 @@ def respect_order(landmarks: list, A_eq, b_eq): | |||||||
|             A_eq = np.vstack((A_eq,l)) |             A_eq = np.vstack((A_eq,l)) | ||||||
|             b_eq.append(0) |             b_eq.append(0) | ||||||
|  |  | ||||||
|             for i in range(7): |             """for i in range(7): | ||||||
|                 print(l[i*7:i*7+7]) |                 print(l[i*7:i*7+7]) | ||||||
|             print("\n") |             print("\n")""" | ||||||
|  |  | ||||||
|     return A_eq, b_eq |     return A_eq, b_eq | ||||||
|  |  | ||||||
| @@ -268,7 +327,19 @@ A_eq, b_eq = respect_order(landmarks, A_eq, b_eq)              # Respect order o | |||||||
| x_bounds = [(0, 1)] * len(c) | x_bounds = [(0, 1)] * len(c) | ||||||
|  |  | ||||||
| # Solve linear programming problem | # Solve linear programming problem | ||||||
|  |  | ||||||
| res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) | res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) | ||||||
|  | circle = has_circle(res.x) | ||||||
|  |  | ||||||
|  | while len(circle) != 0 : | ||||||
|  |     print("The solution has a circular path. Not interpretable.") | ||||||
|  |     print("Need to add constraints until no circle ") | ||||||
|  |  | ||||||
|  |     A_ub, b_ub = prevent_circle(landmarks, A_ub, b_ub, circle) | ||||||
|  |     res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) | ||||||
|  |     circle = has_circle(res.x) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Raise error if no solution is found | # Raise error if no solution is found | ||||||
| if not res.success : | if not res.success : | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user