Skip to content

Commit 70bf89d

Browse files
Update flow.py
1 parent f402a67 commit 70bf89d

File tree

1 file changed

+32
-32
lines changed

1 file changed

+32
-32
lines changed

spopt/locate/flow.py

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,10 @@ def get_flow_coverage(self) -> None:
409409

410410
self.flow_coverage[od_pair] = {
411411
"flow_volume": flow_volume,
412-
"covered_proportion": covered_proportion,
413-
"covered_volume": flow_volume * covered_proportion,
412+
"covered_proportion": round(covered_proportion, 2),
413+
"covered_volume": round(
414+
flow_volume * covered_proportion, 2
415+
),
414416
}
415417

416418
total_covered_volume = sum(
@@ -420,9 +422,9 @@ def get_flow_coverage(self) -> None:
420422
coverage["flow_volume"] for coverage in self.flow_coverage.values()
421423
)
422424
return {
423-
"covered_volume": total_covered_volume,
424-
"flow_volume": flow_volume,
425-
"covered_proportion": total_covered_volume / flow_volume,
425+
"covered_volume": round(total_covered_volume, 2),
426+
"flow_volume": round(flow_volume, 2),
427+
"covered_proportion": round(total_covered_volume / flow_volume, 2),
426428
}
427429

428430
def get_vmt_coverage(self) -> Dict[str, float]:
@@ -449,9 +451,7 @@ def get_vmt_coverage(self) -> Dict[str, float]:
449451

450452

451453
class FRLMNodeCoverageMixin:
452-
453454
def calculate_covered_nodes(self) -> None:
454-
455455
if self.threshold <= 0:
456456
self.covered_nodes = []
457457
return
@@ -493,9 +493,7 @@ def get_node_coverage_percentage(self) -> float:
493493

494494

495495
class FRLMSolverStatsMixin:
496-
497496
def extract_solver_statistics(self) -> None:
498-
499497
if not hasattr(self, "model") or self.model is None:
500498
raise AttributeError("Model must be solved first. Call solve().")
501499

@@ -539,19 +537,23 @@ def get_detailed_results(self) -> Dict:
539537
if not hasattr(self, "solver_stats"):
540538
self.extract_solver_statistics()
541539

540+
model_params = {
541+
"vehicle_range": round(self.vehicle_range, 2),
542+
"p_facilities": self.p_facilities,
543+
"capacity": self.capacity,
544+
"threshold": self.threshold,
545+
"objective_type": self.objective,
546+
}
547+
548+
if self.threshold > 0:
549+
model_params["weight"] = self.weight
550+
542551
results = {
543-
"model_parameters": {
544-
"vehicle_range": self.vehicle_range,
545-
"p_facilities": self.p_facilities,
546-
"capacity": self.capacity,
547-
"threshold": self.threshold,
548-
"weight": self.weight,
549-
"objective_type": self.objective,
550-
},
552+
"model_parameters": model_params,
551553
"solution": {
552554
"status": self.status,
553555
"objective_value": self.objective_value,
554-
"selected_facilities": self.selected_facilities,
556+
"selected_facilities": list(self.selected_facilities.keys()),
555557
"solution_time": self.solution_time,
556558
},
557559
"solver_statistics": self.solver_stats,
@@ -1206,7 +1208,6 @@ def calculate_node_weights(self, include_destination: bool = False) -> np.ndarra
12061208
total_flow = sum(self.flows.values())
12071209

12081210
for (origin, destination), volume in self.flows.items():
1209-
12101211
node_weights[origin] += volume
12111212

12121213
if include_destination:
@@ -1337,7 +1338,7 @@ def solve(
13371338
Additional solver-specific parameters
13381339
"""
13391340
if not self._model_built:
1340-
raise ValueError("Model must be built first.")
1341+
self._build_model()
13411342

13421343
threshold = kwargs.get("threshold", self.threshold)
13431344
weight = kwargs.get("weight", self.weight)
@@ -1378,8 +1379,8 @@ def solve(
13781379

13791380
return {
13801381
"status": self.status,
1381-
"objective_value": self.objective_value,
1382-
"selected_facilities": self.selected_facilities,
1382+
"objective_value": round(self.objective_value),
1383+
"selected_facilities": list(self.selected_facilities.keys()),
13831384
}
13841385

13851386
def _solve_greedy(
@@ -1514,7 +1515,7 @@ def _solve_greedy(
15141515

15151516
self.objective_value = current_objective
15161517
# Final evaluation
1517-
self.solution_time = time.time() - start_time
1518+
self.solution_time = round(time.time() - start_time, 2)
15181519
self.status = "Heuristic"
15191520
for k, site in enumerate(self.candidate_sites):
15201521
self.facility_vars[k].varValue = current_facilities.get(site, 0)
@@ -1523,8 +1524,8 @@ def _solve_greedy(
15231524
result = {
15241525
"status": self.status,
15251526
"model_type": "use ac_pc" if self.use_ac_pc else " use combination",
1526-
"objective_value": self.objective_value,
1527-
"selected_facilities": self.selected_facilities,
1527+
"objective_value": round(self.objective_value, 2),
1528+
"selected_facilities": list(self.selected_facilities.keys()),
15281529
"objective_type": objective,
15291530
"flow_coverage": self.flow_coverage,
15301531
}
@@ -1903,7 +1904,7 @@ def _solve_pulp(
19031904
"No solver instance provided. Please specify a valid PuLP solver."
19041905
)
19051906

1906-
self.solution_time = time.time() - start_time
1907+
self.solution_time = round(time.time() - start_time, 2)
19071908
self.pulp_status = self.model.status
19081909
self.status = pulp.LpStatus[self.model.status]
19091910

@@ -1922,9 +1923,9 @@ def _solve_pulp(
19221923
result = {
19231924
"status": self.status,
19241925
"model_type": "ac_pc" if self.use_ac_pc else "combination",
1925-
"objective_value": self.objective_value,
1926-
"selected_facilities": self.selected_facilities, # Property will be called
1927-
"solution_time": self.solution_time,
1926+
"objective_value": round(self.objective_value, 2),
1927+
"selected_facilities": list(self.selected_facilities.keys()),
1928+
"solution_time": round(self.solution_time, 2),
19281929
"objective_type": objective,
19291930
}
19301931
return result
@@ -2013,7 +2014,6 @@ def _evaluate_capacitated_solution(self, facilities: Dict[Any, int]) -> Dict:
20132014
}
20142015

20152016
def _initialize_greedy_solution(self, method: str) -> set:
2016-
20172017
supported_methods = ["empty", "random", "central", "high_flow"]
20182018

20192019
if method not in supported_methods:
@@ -2316,7 +2316,6 @@ def _estimate_facility_shadow_price(self) -> float:
23162316
return best_improvement
23172317

23182318
def get_shadow_prices(self) -> Dict:
2319-
23202319
if self.solver_type == "pulp":
23212320
shadow_prices = self.shadow_prices.copy()
23222321
elif self.solver_type == "greedy":
@@ -2504,8 +2503,9 @@ def __repr__(self):
25042503
f", capacity={self.capacity}" if self.capacity is not None else ""
25052504
)
25062505
threshold_info = f", threshold={self.threshold}" if self.threshold > 0 else ""
2506+
weight_info = f", weight={self.weight}" if self.threshold > 0 else ""
25072507

25082508
return (
25092509
f"FRLM({range_str}, p={self.p_facilities}{capacity_info}"
2510-
f"{threshold_info}, weight={self.weight})"
2510+
f"{threshold_info}{weight_info})"
25112511
)

0 commit comments

Comments
 (0)