整合求解器活动监控与步长回归证据
同步远端 PNL0003 诊断和大采样网格能力,语义合并活动感知的 60 秒真停滞判定与旧后端 15 分钟兼容兜底。 纳管热路径优化、15 单元运行证据、浏览器与 API 报告,并补充北京时间更新日志和遗留问题。
This commit is contained in:
1 parent
c19cf77aee
commit
e18399c022
46 files changed
+181589
-170
No files matched your search
@@ -399,6 +399,19 @@ def _case_observation(
|
||||
checkpoint_details.append(detail)
|
||||
if not detail["available"]:
|
||||
issues.append("checkpointUnavailable")
|
||||
requested_time = checkpoint.get("requestedTime")
|
||||
actual_time = checkpoint.get("actualTime")
|
||||
if (
|
||||
not isinstance(requested_time, (int, float))
|
||||
or not isinstance(actual_time, (int, float))
|
||||
or not math.isclose(
|
||||
float(requested_time),
|
||||
float(actual_time),
|
||||
rel_tol=0.0,
|
||||
abs_tol=tolerance.checkpoint_time_absolute_seconds,
|
||||
)
|
||||
):
|
||||
issues.append("checkpointTimeMismatch")
|
||||
if expected_projection_count is not None and len(state_values) != int(
|
||||
expected_projection_count
|
||||
):
|
||||
@@ -455,6 +468,7 @@ def _pair_checkpoints(
|
||||
right: Mapping[str, object],
|
||||
*,
|
||||
tolerance: MatrixTolerance,
|
||||
strict_prefix_stop: float | None = None,
|
||||
) -> dict[str, object]:
|
||||
left_checkpoints = _checkpoints(_summary(left))
|
||||
right_checkpoints = _checkpoints(_summary(right))
|
||||
@@ -463,6 +477,11 @@ def _pair_checkpoints(
|
||||
left_time = left_checkpoint.get("requestedTime")
|
||||
if not isinstance(left_time, (int, float)):
|
||||
continue
|
||||
if strict_prefix_stop is not None and not (
|
||||
float(left_time)
|
||||
< strict_prefix_stop - tolerance.checkpoint_time_absolute_seconds
|
||||
):
|
||||
continue
|
||||
match = next(
|
||||
(
|
||||
right_checkpoint
|
||||
@@ -554,6 +573,7 @@ def _pair_checkpoints(
|
||||
"commonCheckpointTimes": [
|
||||
pair[0].get("requestedTime") for pair in paired
|
||||
],
|
||||
"strictPrefixStopTime": strict_prefix_stop,
|
||||
"valueMismatchCount": mismatch_count,
|
||||
"keySetMismatchCount": key_set_mismatch_count,
|
||||
"nonnumericValueCount": nonnumeric_count,
|
||||
@@ -569,6 +589,7 @@ def _compare_time_sequences(
|
||||
*,
|
||||
prefix_stop: float,
|
||||
absolute_tolerance: float,
|
||||
strict_prefix: bool,
|
||||
) -> dict[str, object]:
|
||||
left_times = _finite_event_times(left)
|
||||
right_times = _finite_event_times(right)
|
||||
@@ -579,12 +600,12 @@ def _compare_time_sequences(
|
||||
"left": left,
|
||||
"right": right,
|
||||
}
|
||||
left_prefix = [
|
||||
value for value in left_times if value <= prefix_stop + absolute_tolerance
|
||||
]
|
||||
right_prefix = [
|
||||
value for value in right_times if value <= prefix_stop + absolute_tolerance
|
||||
]
|
||||
if strict_prefix:
|
||||
include = lambda value: value < prefix_stop - absolute_tolerance
|
||||
else:
|
||||
include = lambda value: value <= prefix_stop + absolute_tolerance
|
||||
left_prefix = [value for value in left_times if include(value)]
|
||||
right_prefix = [value for value in right_times if include(value)]
|
||||
passed = len(left_prefix) == len(right_prefix) and all(
|
||||
math.isclose(
|
||||
left_value,
|
||||
@@ -607,6 +628,7 @@ def _pair_events(
|
||||
right: Mapping[str, object],
|
||||
*,
|
||||
prefix_stop: float,
|
||||
strict_prefix: bool,
|
||||
tolerance: MatrixTolerance,
|
||||
) -> dict[str, object]:
|
||||
left_trace = _event_trace(_summary(left))
|
||||
@@ -616,12 +638,14 @@ def _pair_events(
|
||||
right_trace.get("signalEventTimes"),
|
||||
prefix_stop=prefix_stop,
|
||||
absolute_tolerance=tolerance.signal_event_time_absolute_seconds,
|
||||
strict_prefix=strict_prefix,
|
||||
)
|
||||
mechanical = _compare_time_sequences(
|
||||
left_trace.get("mechanicalTransitionTimes"),
|
||||
right_trace.get("mechanicalTransitionTimes"),
|
||||
prefix_stop=prefix_stop,
|
||||
absolute_tolerance=tolerance.event_time_absolute_seconds,
|
||||
strict_prefix=strict_prefix,
|
||||
)
|
||||
availability = (
|
||||
left_trace.get("mechanicalTransitionTimesAvailable") is not False
|
||||
@@ -631,6 +655,7 @@ def _pair_events(
|
||||
"evaluated": bool(left_trace) and bool(right_trace),
|
||||
"passed": bool(signal["passed"] and mechanical["passed"] and availability),
|
||||
"prefixStopTime": prefix_stop,
|
||||
"strictPrefix": strict_prefix,
|
||||
"signalEventTimes": signal,
|
||||
"mechanicalTransitionTimes": mechanical,
|
||||
"mechanicalTransitionTimesAvailable": availability,
|
||||
@@ -701,17 +726,29 @@ def compare_matrix_cases(
|
||||
left_stop = float(left["stopTime"])
|
||||
right_stop = float(right["stopTime"])
|
||||
prefix_stop = min(left_stop, right_stop)
|
||||
strict_prefix = not math.isclose(
|
||||
left_stop,
|
||||
right_stop,
|
||||
rel_tol=0.0,
|
||||
abs_tol=tolerance.checkpoint_time_absolute_seconds,
|
||||
)
|
||||
if not _completed(left, left_stop) or not _completed(right, right_stop):
|
||||
return {
|
||||
"evaluated": False,
|
||||
"passed": False,
|
||||
"reason": "oneOrBothCasesDidNotComplete",
|
||||
}
|
||||
state = _pair_checkpoints(left, right, tolerance=tolerance)
|
||||
state = _pair_checkpoints(
|
||||
left,
|
||||
right,
|
||||
tolerance=tolerance,
|
||||
strict_prefix_stop=prefix_stop if strict_prefix else None,
|
||||
)
|
||||
events = _pair_events(
|
||||
left,
|
||||
right,
|
||||
prefix_stop=prefix_stop,
|
||||
strict_prefix=strict_prefix,
|
||||
tolerance=tolerance,
|
||||
)
|
||||
diagnostics = _pair_diagnostics(
|
||||
@@ -728,6 +765,7 @@ def compare_matrix_cases(
|
||||
"evaluated": True,
|
||||
"passed": passed,
|
||||
"commonPrefixStopTime": prefix_stop,
|
||||
"strictPrefix": strict_prefix,
|
||||
"stateProjection": state,
|
||||
"events": events,
|
||||
"diagnostics": diagnostics,
|
||||
@@ -874,6 +912,36 @@ def run_max_step_matrix(
|
||||
if sampling_mode == "source"
|
||||
else _finite_positive(lane_config.get("sampleStep"), field="lane.sampleStep")
|
||||
)
|
||||
source_start = float(source_config["tStart"])
|
||||
checkpoint_grid_tolerance = max(
|
||||
1.0e-12,
|
||||
8.0 * math.ulp(max(1.0, abs(source_start))),
|
||||
8.0 * math.ulp(max(1.0, abs(sample_step))),
|
||||
)
|
||||
for horizon in selected_horizons:
|
||||
for checkpoint_time in horizon.checkpoint_times:
|
||||
if math.isclose(
|
||||
checkpoint_time,
|
||||
horizon.stop_time,
|
||||
rel_tol=0.0,
|
||||
abs_tol=checkpoint_grid_tolerance,
|
||||
):
|
||||
continue
|
||||
grid_index = round((checkpoint_time - source_start) / sample_step)
|
||||
grid_time = source_start + grid_index * sample_step
|
||||
if not math.isclose(
|
||||
checkpoint_time,
|
||||
grid_time,
|
||||
rel_tol=0.0,
|
||||
abs_tol=checkpoint_grid_tolerance,
|
||||
):
|
||||
raise RegressionManifestError(
|
||||
"Matrix checkpoint "
|
||||
f"{checkpoint_time:.17g} is not represented by the "
|
||||
f"{sample_step:.17g} s output grid for "
|
||||
f"{horizon.case_id!r}; use the event trace for off-grid "
|
||||
"transition times."
|
||||
)
|
||||
instrumentation_mode = str(
|
||||
lane_config.get("instrumentationMode", "standard")
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user