good starting point, working pulp

This commit is contained in:
Helldragon67 2025-01-15 19:55:48 +01:00
parent 814da4b5f6
commit 3ebe0b7191
2 changed files with 15 additions and 25 deletions

View File

@ -11,7 +11,7 @@ def client():
"""Client used to call the app.""" """Client used to call the app."""
return TestClient(app) return TestClient(app)
'''
def test_turckheim(client, request): # pylint: disable=redefined-outer-name def test_turckheim(client, request): # pylint: disable=redefined-outer-name
""" """
Test n°1 : Custom test in Turckheim to ensure small villages are also supported. Test n°1 : Custom test in Turckheim to ensure small villages are also supported.
@ -45,8 +45,8 @@ def test_turckheim(client, request): # pylint: disable=redefined-outer-name
# Add details to report # Add details to report
log_trip_details(request, landmarks, result['total_time'], duration_minutes) log_trip_details(request, landmarks, result['total_time'], duration_minutes)
for elem in landmarks : # for elem in landmarks :
print(elem) # print(elem)
# checks : # checks :
assert response.status_code == 200 # check for successful planning assert response.status_code == 200 # check for successful planning
@ -54,8 +54,8 @@ def test_turckheim(client, request): # pylint: disable=redefined-outer-name
assert duration_minutes*0.8 < int(result['total_time']) < duration_minutes*1.2 assert duration_minutes*0.8 < int(result['total_time']) < duration_minutes*1.2
assert len(landmarks) > 2 # check that there is something to visit assert len(landmarks) > 2 # check that there is something to visit
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds" assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
assert 2==3 # assert 2==3
'''
def test_bellecour(client, request) : # pylint: disable=redefined-outer-name def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
@ -97,9 +97,9 @@ def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
assert response.status_code == 200 # check for successful planning assert response.status_code == 200 # check for successful planning
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds" assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
assert duration_minutes*0.8 < int(result['total_time']) < duration_minutes*1.2 assert duration_minutes*0.8 < int(result['total_time']) < duration_minutes*1.2
assert 2 == 3 # assert 2 == 3
'''
def test_Paris(client, request) : # pylint: disable=redefined-outer-name def test_Paris(client, request) : # pylint: disable=redefined-outer-name
""" """
Test n°2 : Custom test in Paris (les Halles) centre to ensure proper decision making in crowded area. Test n°2 : Custom test in Paris (les Halles) centre to ensure proper decision making in crowded area.
@ -131,8 +131,8 @@ def test_Paris(client, request) : # pylint: disable=redefined-outer-name
# Add details to report # Add details to report
log_trip_details(request, landmarks, result['total_time'], duration_minutes) log_trip_details(request, landmarks, result['total_time'], duration_minutes)
# for elem in landmarks : for elem in landmarks :
# print(elem) print(elem)
# checks : # checks :
assert response.status_code == 200 # check for successful planning assert response.status_code == 200 # check for successful planning
@ -171,8 +171,8 @@ def test_New_York(client, request) : # pylint: disable=redefined-outer-name
# Add details to report # Add details to report
log_trip_details(request, landmarks, result['total_time'], duration_minutes) log_trip_details(request, landmarks, result['total_time'], duration_minutes)
# for elem in landmarks : for elem in landmarks :
# print(elem) print(elem)
# checks : # checks :
assert response.status_code == 200 # check for successful planning assert response.status_code == 200 # check for successful planning
@ -211,14 +211,14 @@ def test_shopping(client, request) : # pylint: disable=redefined-outer-name
# Add details to report # Add details to report
log_trip_details(request, landmarks, result['total_time'], duration_minutes) log_trip_details(request, landmarks, result['total_time'], duration_minutes)
# for elem in landmarks : for elem in landmarks :
# print(elem) print(elem)
# checks : # checks :
assert response.status_code == 200 # check for successful planning assert response.status_code == 200 # check for successful planning
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds" assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
assert duration_minutes*0.8 < int(result['total_time']) < duration_minutes*1.2 assert duration_minutes*0.8 < int(result['total_time']) < duration_minutes*1.2
'''
# def test_new_trip_single_prefs(client): # def test_new_trip_single_prefs(client):
# response = client.post( # response = client.post(

View File

@ -2,7 +2,6 @@ import yaml, logging
import numpy as np import numpy as np
import pulp as pl import pulp as pl
from scipy.optimize import linprog from scipy.optimize import linprog
from scipy.sparse import lil_matrix, csr_matrix
from collections import defaultdict, deque from collections import defaultdict, deque
from ..structs.landmark import Landmark from ..structs.landmark import Landmark
@ -508,21 +507,14 @@ class Optimizer:
# SET CONSTRAINTS FOR INEQUALITY # 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. 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). 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. 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 # SET CONSTRAINTS FOR EQUALITY
print("ok3")
A_eq, b_eq = self.init_eq_not_stay(landmarks) # Force solution not to stay in same place 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 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) 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. 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.") self.logger.debug(f"Optimizing with {A_ub.shape[0]} + {A_eq.shape[0]} = {A_ub.shape[0] + A_eq.shape[0]} constraints.")
@ -545,14 +537,12 @@ class Optimizer:
prob += (pl.lpSum([A_eq[i][j] * x[j] for j in range(L*L)]) == b_eq[i]) prob += (pl.lpSum([A_eq[i][j] * x[j] for j in range(L*L)]) == b_eq[i])
# 6. Solve the problem # 6. Solve the problem
prob.solve(pl.PULP_CBC_CMD(msg=False)) prob.solve(pl.PULP_CBC_CMD(msg=False, gapRel=0.3))
# 7. Extract Results # 7. Extract Results
status = pl.LpStatus[prob.status] status = pl.LpStatus[prob.status]
solution = [pl.value(var) for var in x] # The values of the decision variables (will be 0 or 1) solution = [pl.value(var) for var in x] # The values of the decision variables (will be 0 or 1)
print(status)
self.logger.debug("First results are out. Looking out for circles and correcting.") self.logger.debug("First results are out. Looking out for circles and correcting.")
# Raise error if no solution is found. FIXME: for now this throws the internal server error # Raise error if no solution is found. FIXME: for now this throws the internal server error