Spaces:
Running
Running
File size: 1,704 Bytes
4d0ffdd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
"""Basic metrics for scheduler evaluation.
These helpers avoid heavy dependencies and can be used by scripts.
"""
from __future__ import annotations
from typing import Iterable, List, Tuple
def gini(values: Iterable[float]) -> float:
"""Compute the Gini coefficient for a non-negative list of values.
Args:
values: Sequence of non-negative numbers
Returns:
Gini coefficient in [0, 1]
"""
vals = [v for v in values if v is not None]
n = len(vals)
if n == 0:
return 0.0
if min(vals) < 0:
raise ValueError("Gini expects non-negative values")
sorted_vals = sorted(vals)
cum = 0.0
for i, x in enumerate(sorted_vals, start=1):
cum += i * x
total = sum(sorted_vals)
if total == 0:
return 0.0
# Gini formula: (2*sum(i*x_i)/(n*sum(x)) - (n+1)/n)
return (2 * cum) / (n * total) - (n + 1) / n
def utilization(total_scheduled: int, capacity: int) -> float:
"""Compute utilization as scheduled/capacity.
Args:
total_scheduled: Number of scheduled hearings
capacity: Total available slots
"""
if capacity <= 0:
return 0.0
return min(1.0, total_scheduled / capacity)
def urgency_sla(records: List[Tuple[bool, int]], days: int = 7) -> float:
"""Compute SLA for urgent cases.
Args:
records: List of tuples (is_urgent, working_day_delay)
days: SLA threshold in working days
Returns:
Proportion of urgent cases within SLA (0..1)
"""
urgent = [delay for is_urgent, delay in records if is_urgent]
if not urgent:
return 1.0
within = sum(1 for d in urgent if d <= days)
return within / len(urgent)
|