P4Learned Delivery Routing
1 Codebase

test_nn_data.py

tests/test_nn_data.py · 68 lines · Download

1import numpy as np2import pytest3 4from delivery.baselines import DistanceLinear, HistoricalAverage5from delivery.data import load_fixture6from delivery.instances import generate_instance7from delivery.nn import TrainConfig, TravelTimeNN, numerical_grad_check, train8from delivery.travel_time import TimeModel9 10 11@pytest.fixture(scope="module")12def fixture_data():13    return load_fixture()14 15 16def test_backprop_matches_finite_differences():17    assert numerical_grad_check() < 1e-518 19 20def test_fixture_schema_and_filters(fixture_data):21    trips, zones, dist = fixture_data22    for c in ("pu", "do", "hour", "weekday", "duration_min", "distance_mi", "split", "date"):23        assert c in trips.columns24    assert trips.duration_min.between(1, 120).all()25    assert (trips.weekday < 5).all()26    assert len(zones) == 20 and dist.shape == (20, 20)27    # split by day: no date appears in two splits and the test week comes last28    by = trips.groupby("split").date.agg(["min", "max"])29    assert by.loc["train", "max"] < by.loc["val", "min"] <= by.loc["val", "max"] < by.loc["test", "min"]30 31 32def test_nn_trains_and_beats_global_mean_on_fixture(fixture_data, tmp_path):33    trips, zones, dist = fixture_data34    tr, va, te = (trips[trips.split == s] for s in ("train", "val", "test"))35    m = train(tr, va, len(zones), dist, TrainConfig(epochs=25, patience=5, batch=128), verbose=False)36    args = [te[c].values for c in ("pu", "do", "hour", "weekday")]37    nn_mae = np.abs(m.predict(*args) - te.duration_min.values).mean()38    mean_mae = np.abs(tr.duration_min.mean() - te.duration_min.values).mean()39    assert nn_mae < mean_mae40    m.save(tmp_path / "m.npz")41    m2 = TravelTimeNN.load(tmp_path / "m.npz")42    assert np.allclose(m.predict(*args), m2.predict(*args))43 44 45def test_baselines_fit_and_back_off(fixture_data):46    trips, zones, dist = fixture_data47    tr = trips[trips.split == "train"]48    h = HistoricalAverage(20).fit(tr)49    assert np.isfinite(h.table).all()50    lin = DistanceLinear(dist).fit(tr)51    assert lin.slope_ > 0          # longer typical distance -> longer trips52 53 54def test_generator_is_seeded():55    a = generate_instance(20, 7).to_dict()56    b = generate_instance(20, 7).to_dict()57    c = generate_instance(20, 8).to_dict()58    assert a == b and a != c59    assert all(o["latest"] > o["earliest"] for o in a["orders"])60 61 62def test_time_model_interpolation_is_fifo_and_exact_at_knots():63    M = np.stack([np.full((2, 2), 10.0 + h) for h in range(24)])64    tm = TimeModel(M, factor=1.2)65    assert tm.tt(0, 1, 8 * 60 + 30) == pytest.approx(18 * 1.2)66    assert tm.tt(0, 1, 9 * 60) == pytest.approx(18.5 * 1.2)67    assert tm.is_fifo()68    assert (tm.lower_bound_matrix(600) <= tm.M[10]).all()