完善通用求解器回归与前端交互

- 引入因果坐标内核、热流体恢复和递进长时回归\n- 完善正交连线、线桥、视图保持与结果曲线缩放\n- 补充依赖约束、CI、测试基线和北京时间更新日志
This commit is contained in:
lujingze committed 2026-08-18 06:42:07 +00:00
1 parent 143e8dd309
commit b435daecf2
65 files changed
+172271 -701

No files matched your search

+492 -26
View File
@@ -31,6 +31,10 @@ PRESSURE_LOWER_BOUND_PA = 0.0
CAUSAL_FAST_PATH_ENVIRONMENT_VARIABLE = "SIMULATION_CAUSAL_FAST_PATH"
CAUSAL_EXECUTOR_V2_ENVIRONMENT_VARIABLE = "SIMULATION_CAUSAL_EXECUTOR_V2"
CAUSAL_COORDINATE_KERNEL_ENVIRONMENT_VARIABLE = (
"SIMULATION_CAUSAL_COORDINATE_KERNEL"
)
CAUSAL_FAST_PATH_AUDIT_INTERVAL = 64
@@ -39,6 +43,20 @@ def _causal_fast_path_environment_enabled() -> bool:
return value.strip().lower() not in {"0", "false", "no", "off"}
def _causal_executor_v2_environment_enabled() -> bool:
"""Return whether the allocation-light causal executor is enabled."""
value = os.getenv(CAUSAL_EXECUTOR_V2_ENVIRONMENT_VARIABLE, "1")
return value.strip().lower() not in {"0", "false", "no", "off"}
def _causal_coordinate_kernel_environment_enabled() -> bool:
"""Return whether the canonical-coordinate causal kernel is enabled."""
value = os.getenv(CAUSAL_COORDINATE_KERNEL_ENVIRONMENT_VARIABLE, "1")
return value.strip().lower() not in {"0", "false", "no", "off"}
class AlgebraicSolveError(RuntimeError):
def __init__(
self,
@@ -120,6 +138,42 @@ class CausalEffortAssignment:
anchor: EffortAnchor
@dataclass(frozen=True)
class CausalEffortKernelTarget:
"""One canonical effort coordinate extracted from a residual evaluator."""
coordinate_index: int
assignment: CausalEffortAssignment
equation_index: int
equation_id: str
@dataclass(frozen=True)
class CausalEffortKernelEvaluation:
"""One component call shared by every state anchor that it owns."""
evaluate: Callable[[], tuple[float, ...]]
targets: tuple[CausalEffortKernelTarget, ...]
@dataclass(frozen=True)
class CausalEffortKernelStage:
"""Precompiled canonical coordinates and compatibility broadcasts."""
variable: str
assignments: tuple[tuple[int, CausalEffortAssignment], ...]
direct_targets: tuple[tuple[int, CausalEffortAssignment], ...]
component_evaluations: tuple[CausalEffortKernelEvaluation, ...]
@dataclass(frozen=True)
class CausalFlowKernelStage:
"""Map one existing dependency stage into the canonical workspace."""
stage: ExplicitFlowStage
coordinate_indices: tuple[int, ...]
@dataclass(frozen=True)
class ConnectionEquationEvaluation:
template: EquationResidual
@@ -366,6 +420,56 @@ class PressureFlowSolver:
self._causal_fast_path_environment_enabled = (
_causal_fast_path_environment_enabled()
)
self._causal_executor_v2_environment_enabled = (
_causal_executor_v2_environment_enabled()
)
self._causal_coordinate_kernel_environment_enabled = (
_causal_coordinate_kernel_environment_enabled()
)
self._causal_compiled_effort_unknown_count = sum(
len(assignment.members)
for assignments in self._causal_effort_plan_by_variable.values()
for assignment in assignments
)
self._causal_compiled_flow_assignment_count = sum(
len(stage.assignments) for stage in self._explicit_flow_plan
)
self._causal_external_effort_unknowns = tuple(
member
for variable in ("x", "v")
for assignment in self._causal_effort_plan_by_variable.get(
variable, ()
)
for member in assignment.members
)
self._causal_external_x_states = tuple(
unknown.state
for unknown in self._causal_external_effort_unknowns
if unknown.variable == "x"
)
self._causal_external_v_states = tuple(
unknown.state
for unknown in self._causal_external_effort_unknowns
if unknown.variable == "v"
)
(
self._causal_effort_kernel_by_variable,
self._causal_flow_kernel_plan,
self._causal_coordinate_values,
) = self._compile_causal_coordinate_kernel()
self._causal_logical_effort_coordinate_count = sum(
len(stage.assignments)
for stage in self._causal_effort_kernel_by_variable.values()
)
self._causal_eliminated_effort_alias_count = max(
self._causal_compiled_effort_unknown_count
- self._causal_logical_effort_coordinate_count,
0,
)
self._causal_compatibility_scatter_count = (
self._causal_compiled_effort_unknown_count
+ self._causal_compiled_flow_assignment_count
)
self._causal_runtime_disabled_reason: str | None = None
self._causal_audit_interval = CAUSAL_FAST_PATH_AUDIT_INTERVAL
self._causal_audit_required = True
@@ -374,7 +478,11 @@ class PressureFlowSolver:
self._causal_full_residual_audit_count = 0
self._causal_audit_failure_count = 0
self._causal_legacy_fallback_count = 0
self._causal_v2_fast_solve_count = 0
self._causal_v2_runtime_validation_failure_count = 0
self._causal_coordinate_fast_solve_count = 0
self._causal_last_verified_diagnostics: AlgebraicSolveDiagnostics | None = None
self._causal_cached_fast_diagnostics: AlgebraicSolveDiagnostics | None = None
self.last_diagnostics: AlgebraicSolveDiagnostics | None = None
@property
@@ -435,6 +543,25 @@ class PressureFlowSolver:
and self._causal_runtime_disabled_reason is None
)
@property
def causal_executor_v2_enabled(self) -> bool:
"""Whether this run may use the v2 executor (environment opt-out)."""
return (
self._causal_executor_v2_environment_enabled
and self.causal_fast_path_enabled
)
@property
def causal_coordinate_kernel_enabled(self) -> bool:
"""Whether the canonical-coordinate executor may run now."""
return (
self._causal_coordinate_kernel_environment_enabled
and self.causal_executor_v2_enabled
and bool(self._causal_coordinate_values)
)
def causal_execution_diagnostics(self) -> dict[str, object]:
disabled_reason = self._causal_runtime_disabled_reason
if not self._causal_fast_path_environment_enabled:
@@ -458,6 +585,39 @@ class PressureFlowSolver:
if last_verified is not None
else None
),
"executorV2Configured": self._causal_executor_v2_environment_enabled,
"executorV2Enabled": self.causal_executor_v2_enabled,
"executorV2FastSolveCount": self._causal_v2_fast_solve_count,
"executorV2RuntimeValidationFailureCount": (
self._causal_v2_runtime_validation_failure_count
),
"coordinateKernelConfigured": (
self._causal_coordinate_kernel_environment_enabled
),
"coordinateKernelEnabled": self.causal_coordinate_kernel_enabled,
"coordinateKernelFastSolveCount": (
self._causal_coordinate_fast_solve_count
),
"compiledEffortUnknownCount": (
self._causal_compiled_effort_unknown_count
),
"compiledFlowAssignmentCount": (
self._causal_compiled_flow_assignment_count
),
"compiledAssignmentCount": (
self._causal_compiled_effort_unknown_count
+ self._causal_compiled_flow_assignment_count
),
"logicalEffortCoordinateCount": (
self._causal_logical_effort_coordinate_count
),
"eliminatedEffortAliasCount": (
self._causal_eliminated_effort_alias_count
),
"canonicalCoordinateCount": len(self._causal_coordinate_values),
"compatibilityScatterCount": (
self._causal_compatibility_scatter_count
),
}
def request_causal_audit(self) -> None:
@@ -651,10 +811,163 @@ class PressureFlowSolver:
None,
)
def _compile_causal_coordinate_kernel(
self,
) -> tuple[
dict[str, CausalEffortKernelStage],
tuple[CausalFlowKernelStage, ...],
list[float],
]:
"""Compile independent coordinates without changing public port state.
``PortState`` remains the compatibility surface consumed by component
methods. The workspace stores one value per proven effort equality
group and one per explicit flow assignment; compatibility aliases are
populated only after every target in an effort stage has been checked.
"""
if not self._causal_fast_path_eligible:
return {}, (), []
equation_index_by_id = {
equation.id: index
for index, equation in enumerate(self._equation_templates)
}
effort_stages: dict[str, CausalEffortKernelStage] = {}
next_coordinate = 0
for variable in ("p", "x", "v"):
assignments = self._causal_effort_plan_by_variable.get(variable, ())
indexed_assignments = tuple(
(next_coordinate + offset, assignment)
for offset, assignment in enumerate(assignments)
)
next_coordinate += len(indexed_assignments)
direct_targets: list[tuple[int, CausalEffortAssignment]] = []
targets_by_component: dict[
int,
list[CausalEffortKernelTarget],
] = {}
component_evaluators: dict[int, Callable[[], tuple[float, ...]]] = {}
for coordinate_index, assignment in indexed_assignments:
equation_index = equation_index_by_id[
assignment.anchor.equation_id
]
kind, evaluation_plan, source = (
self._equation_evaluation_locations[equation_index]
)
if kind != "component":
direct_targets.append((coordinate_index, assignment))
continue
component_plan = evaluation_plan
key = id(component_plan)
component_evaluators[key] = component_plan.evaluate
targets_by_component.setdefault(key, []).append(
CausalEffortKernelTarget(
coordinate_index=coordinate_index,
assignment=assignment,
equation_index=source,
equation_id=assignment.anchor.equation_id,
)
)
effort_stages[variable] = CausalEffortKernelStage(
variable=variable,
assignments=indexed_assignments,
direct_targets=tuple(direct_targets),
component_evaluations=tuple(
CausalEffortKernelEvaluation(
evaluate=component_evaluators[key],
targets=tuple(targets),
)
for key, targets in targets_by_component.items()
),
)
flow_stages: list[CausalFlowKernelStage] = []
for stage in self._explicit_flow_plan:
coordinate_indices = tuple(
range(next_coordinate, next_coordinate + len(stage.assignments))
)
next_coordinate += len(stage.assignments)
flow_stages.append(
CausalFlowKernelStage(
stage=stage,
coordinate_indices=coordinate_indices,
)
)
return effort_stages, tuple(flow_stages), [0.0] * next_coordinate
@staticmethod
def _read_effort_anchor(assignment: CausalEffortAssignment) -> float:
state = assignment.anchor.unknown.state
if assignment.variable == "p":
return state.p
if assignment.variable == "x":
return state.x
return state.v
@staticmethod
def _scatter_effort_assignment(
assignment: CausalEffortAssignment,
value: float,
) -> None:
if assignment.variable == "p":
for unknown in assignment.members:
unknown.state.p = value
return
if assignment.variable == "x":
for unknown in assignment.members:
unknown.state.x = value
return
for unknown in assignment.members:
unknown.state.v = value
def _execute_causal_coordinate_effort_plan(
self,
variables: tuple[str, ...],
) -> bool:
"""Evaluate canonical effort coordinates in component-sized batches."""
workspace = self._causal_coordinate_values
for variable in variables:
stage = self._causal_effort_kernel_by_variable.get(variable)
if stage is None:
return False
for coordinate_index, assignment in stage.direct_targets:
workspace[coordinate_index] = (
self._read_effort_anchor(assignment)
- assignment.anchor.evaluate()
)
for evaluation in stage.component_evaluations:
equation_values = evaluation.evaluate()
for target in evaluation.targets:
if target.equation_index >= len(equation_values):
raise RuntimeError(
"Compiled algebraic equation disappeared at runtime: "
f"{target.equation_id}."
)
workspace[target.coordinate_index] = (
self._read_effort_anchor(target.assignment)
- float(equation_values[target.equation_index])
)
for coordinate_index, assignment in stage.assignments:
target = workspace[coordinate_index]
if not isfinite(target) or (
variable == "p" and target <= PRESSURE_LOWER_BOUND_PA
):
return False
for coordinate_index, assignment in stage.assignments:
self._scatter_effort_assignment(
assignment,
workspace[coordinate_index],
)
return True
def _execute_causal_effort_plan(
self,
variables: tuple[str, ...],
) -> bool:
if self.causal_coordinate_kernel_enabled:
return self._execute_causal_coordinate_effort_plan(variables)
for variable in variables:
assignments = self._causal_effort_plan_by_variable.get(variable)
if assignments is None:
@@ -685,15 +998,8 @@ class PressureFlowSolver:
self._causal_solves_since_audit = 0
self._causal_audit_required = False
self._causal_last_verified_diagnostics = diagnostics
def _causal_fast_diagnostics(
self,
) -> AlgebraicSolveDiagnostics:
verified = self._causal_last_verified_diagnostics
if verified is None:
raise RuntimeError("Causal execution has no verified residual baseline.")
return replace(
verified,
self._causal_cached_fast_diagnostics = replace(
diagnostics,
message=(
"Compiled causal pressure-flow program completed; residuals "
"reuse the latest full audit."
@@ -709,6 +1015,14 @@ class PressureFlowSolver:
causal_fast_path_used=True,
)
def _causal_fast_diagnostics(
self,
) -> AlgebraicSolveDiagnostics:
cached = self._causal_cached_fast_diagnostics
if cached is None:
raise RuntimeError("Causal execution has no verified residual baseline.")
return cached
def _build_jacobian_sparsity(self):
"""Compile the residual dependency contract into one CSR pattern.
@@ -1024,6 +1338,10 @@ class PressureFlowSolver:
unknown = sorted(set(variables) - set(self._effort_groups))
if unknown:
raise ValueError("Unsupported effort variables: " + ", ".join(unknown))
if self.causal_coordinate_kernel_enabled:
if self._execute_causal_coordinate_effort_plan(variables):
return
self._disable_causal_fast_path("nonFiniteCausalEffortAnchor")
for variable in variables:
self._seed_equal_effort(variable)
@@ -1835,6 +2153,121 @@ class PressureFlowSolver:
seeded_ids.add(assignment.unknown.id)
return seeded_ids
def _execute_compiled_causal_flow_plan(self) -> str | None:
"""Execute the compile-proven full flow plan without coverage sets."""
if self.causal_coordinate_kernel_enabled:
return self._execute_causal_coordinate_flow_plan()
# Position and velocity are propagated by the mechanical reducer
# before the pressure-only causal solve. They are therefore not
# rewritten below, but remain part of the compiled algebraic contract.
# Validate that small external boundary explicitly instead of restoring
# the legacy scan over every pressure/flow/force unknown.
if any(
not isfinite(unknown.read())
for unknown in self._causal_external_effort_unknowns
):
return "nonFiniteCausalExternalEffort"
reset_unknowns = self._explicit_flow_unknowns_by_variables[
frozenset(("f", "m_flow"))
]
for unknown in reset_unknowns:
unknown.write(0.0)
for stage in self._explicit_flow_plan:
try:
values = self._evaluate_explicit_flow_stage(stage)
except MemoryError:
raise
except (ArithmeticError, RuntimeError, ValueError) as exc:
return f"causalFlowEvaluationFailed:{type(exc).__name__}"
if len(values) != len(stage.assignments):
return "causalFlowAssignmentCountMismatch"
for assignment, target_value in zip(stage.assignments, values):
if not isfinite(target_value):
return "nonFiniteCausalFlowAssignment"
assignment.unknown.write(target_value)
return None
def _execute_causal_coordinate_flow_plan(self) -> str | None:
"""Run flow stages through reusable canonical coordinates."""
if any(not isfinite(state.x) for state in self._causal_external_x_states):
return "nonFiniteCausalExternalEffort"
if any(not isfinite(state.v) for state in self._causal_external_v_states):
return "nonFiniteCausalExternalEffort"
return self._execute_causal_coordinate_flow_stages(
self._causal_flow_kernel_plan,
self._causal_coordinate_values,
)
@staticmethod
def _execute_causal_coordinate_flow_stages(
kernel_plan: tuple[CausalFlowKernelStage, ...],
workspace: list[float],
) -> str | None:
"""Execute proven flow stages without per-call result containers."""
# Residual-based explicit assignments use ``-residual`` and therefore
# require their target coordinate to be zero. Keep this compatibility
# initialization until a component exposes a proven direct target op.
for kernel_stage in kernel_plan:
for assignment in kernel_stage.stage.assignments:
if assignment.unknown.variable == "m_flow":
assignment.unknown.state.m_flow = 0.0
else:
assignment.unknown.state.f = 0.0
for kernel_stage in kernel_plan:
stage = kernel_stage.stage
coordinate_indices = kernel_stage.coordinate_indices
if len(coordinate_indices) != len(stage.assignments):
return "causalFlowAssignmentCountMismatch"
try:
for assignment_index, evaluate in stage.direct_evaluations:
workspace[coordinate_indices[assignment_index]] = float(
evaluate()
)
for evaluation in stage.component_evaluations:
equation_values = evaluation.evaluate()
for assignment_index, equation_index, equation_id in zip(
evaluation.assignment_indices,
evaluation.equation_indices,
evaluation.equation_ids,
):
if equation_index >= len(equation_values):
raise RuntimeError(
"Compiled algebraic equation disappeared at "
f"runtime: {equation_id}."
)
workspace[coordinate_indices[assignment_index]] = (
0.0 - float(equation_values[equation_index])
)
except MemoryError:
raise
except (ArithmeticError, RuntimeError, ValueError) as exc:
return f"causalFlowEvaluationFailed:{type(exc).__name__}"
for assignment, coordinate_index in zip(
stage.assignments,
coordinate_indices,
):
target_value = workspace[coordinate_index]
if not isfinite(target_value):
return "nonFiniteCausalFlowAssignment"
for assignment, coordinate_index in zip(
stage.assignments,
coordinate_indices,
):
target_value = workspace[coordinate_index]
if assignment.unknown.variable == "m_flow":
assignment.unknown.state.m_flow = target_value
else:
assignment.unknown.state.f = target_value
return None
def _build_closed_resistance_pressure_plan(
self,
) -> tuple[ClosedResistancePressureBinding, ...]:
@@ -2088,6 +2521,9 @@ class PressureFlowSolver:
causal_audit_due = (
self._causal_audit_is_due() if causal_candidate else False
)
causal_v2_candidate = (
causal_candidate and self._causal_executor_v2_environment_enabled
)
for component in self._causal_contact_components:
component.clear_causal_contact()
@@ -2100,29 +2536,55 @@ class PressureFlowSolver:
self._disable_causal_fast_path("nonFiniteCausalEffortAnchor")
causal_candidate = False
causal_audit_due = False
causal_v2_candidate = False
self._seed_equal_efforts(effort_variables)
else:
self._seed_equal_efforts(effort_variables)
self._seed_closed_resistance_pressures()
self._seed_resistance_pnl0001_series_pressures()
seeded_flow_ids = self._solve_explicit_flow_unknowns()
contact_bindings = self._seed_unilateral_contacts()
if contact_bindings:
seeded_flow_ids.update(self._solve_explicit_flow_unknowns(("f",)))
self._refresh_unilateral_contacts(contact_bindings)
seeded_flow_ids: set[str] | None = None
contact_bindings: tuple[UnilateralContactBinding, ...] = ()
if causal_v2_candidate:
v2_failure_reason = self._execute_compiled_causal_flow_plan()
if v2_failure_reason is not None:
self._causal_v2_runtime_validation_failure_count += 1
self._causal_legacy_fallback_count += 1
self._disable_causal_fast_path(v2_failure_reason)
causal_candidate = False
causal_audit_due = False
causal_v2_candidate = False
# Rebuild the ordinary seed from scratch in the same solve.
# A partial compiled stage must never influence fallback.
self._seed_equal_efforts(effort_variables)
if not causal_v2_candidate:
self._seed_closed_resistance_pressures()
self._seed_resistance_pnl0001_series_pressures()
seeded_flow_ids = self._solve_explicit_flow_unknowns()
contact_bindings = self._seed_unilateral_contacts()
if contact_bindings:
seeded_flow_ids.update(
self._solve_explicit_flow_unknowns(("f",))
)
self._refresh_unilateral_contacts(contact_bindings)
if causal_candidate:
causal_unknowns_are_feasible = (
not contact_bindings
and seeded_flow_ids == self._causal_flow_unknown_ids
and all(
isfinite(unknown.read())
and (
unknown.variable != "p"
or unknown.read() > PRESSURE_LOWER_BOUND_PA
if causal_v2_candidate:
# Compilation proves a disjoint, complete effort/flow
# partition. The v2 executors validate each produced value,
# so no coverage set or full unknown scan is needed here.
causal_unknowns_are_feasible = True
else:
assert seeded_flow_ids is not None
causal_unknowns_are_feasible = (
not contact_bindings
and seeded_flow_ids == self._causal_flow_unknown_ids
and all(
isfinite(unknown.read())
and (
unknown.variable != "p"
or unknown.read() > PRESSURE_LOWER_BOUND_PA
)
for unknown in self.unknowns
)
for unknown in self.unknowns
)
)
if not causal_unknowns_are_feasible:
self._causal_legacy_fallback_count += 1
self._disable_causal_fast_path("causalRuntimeGateFailed")
@@ -2131,6 +2593,10 @@ class PressureFlowSolver:
elif not causal_audit_due:
diagnostics = self._causal_fast_diagnostics()
self._causal_fast_solve_count += 1
if causal_v2_candidate:
self._causal_v2_fast_solve_count += 1
if self.causal_coordinate_kernel_enabled:
self._causal_coordinate_fast_solve_count += 1
self._causal_solves_since_audit += 1
self.last_diagnostics = diagnostics
return diagnostics