| """StapleBridge training epoch and per-epoch validation. |
| |
| The Full Exact-SB formulation: |
| |
| * finite lead-specific feasible plan support H(x) via |
| ``property_free_hard_plan_support`` (chemistry, geometry, edit budget, |
| sequence identity, protected positions and exact committed-plan completion); |
| * ``q_ref(p|x)`` preserved on the legal plan space then conditioned on the hard |
| mask; |
| * exact finite-support teacher ``q*(p|x) ~ q_ref(p|x) exp(-beta E_T)``; |
| * amortized plan controller ``q_theta(p|x)`` masked and renormalised on the |
| same support; |
| * ``L_plan = KL(q* || q_theta)``; |
| * conditional execution policy trained on canonical-completing trajectories |
| with lead-local positive path weights. |
| |
| ``validate_enabled`` computes the per-epoch validation metrics, including |
| ``q_star_vs_q_theta_kl``, the checkpoint-selection metric. Post-hoc evaluation |
| reporting is not part of this training release. |
| """ |
| from __future__ import annotations |
|
|
| import json |
| import random |
| import time |
| from collections import Counter |
| from typing import Any |
|
|
| import numpy as np |
| import torch |
|
|
| from staplebridge.chemistry.state import StapleState |
| from staplebridge.hydrocarbon.curriculum import build_hydrocarbon_demonstration_path |
| from staplebridge.hydrocarbon.exact_sb_cache import ( |
| energy_only_from_config, resolve_exact_sb_target, |
| ) |
| from staplebridge.hydrocarbon.plan_control import ( |
| HydrocarbonPlanControlConfig, |
| best_committed_plan_trajectory, |
| HydrocarbonPlanHead, |
| completes_committed_plan, |
| controlled_plan_log_probabilities, |
| configured_plan_level_objective, |
| describe_plan, |
| empirical_log_probabilities, |
| hierarchical_plan_ranking_enabled, |
| mask_and_renormalize_plan_log_probabilities, |
| plan_entropy, |
| property_free_hard_plan_support, |
| sample_committed_plan_trajectory, |
| sample_distinct_plans, |
| select_plan_and_trajectory, |
| ) |
| from staplebridge.hydrocarbon.plan_reference import enumerate_legal_plans |
| from staplebridge.hydrocarbon.plan_validation import ( |
| aggregate_q_star_diagnostics, |
| exact_sb_validation_enabled, |
| lead_q_star_diagnostics, |
| ) |
| from staplebridge.hydrocarbon.property_energy import ( |
| HydrocarbonPropertyEnergyConfig, |
| HydrocarbonPropertyScorer, |
| required_original_lead_properties, |
| ) |
| from staplebridge.hydrocarbon.tokenizer import tokenize_sequence |
| from staplebridge.models.control_kernel import state_to_features |
| from staplebridge.training.losses import ( |
| assign_lead_local_positive_weights, |
| compute_weighted_path_loss, |
| ) |
| from staplebridge.training.records import ( |
| beam_decode, summarize, terminal_record, |
| ) |
| from staplebridge.training.trajectory import TransitionStep, WeightedTrajectory |
| from staplebridge.utils.profiling import STAGE_TIMER |
|
|
|
|
| def plan_mode(plan: Any) -> str: |
| return f"{plan.ordered_pair}/i,i+{plan.spacing}" |
|
|
|
|
| def legal_plans(lead: Any, stack: dict[str, Any]) -> list[Any]: |
| return enumerate_legal_plans( |
| tokenize_sequence(lead.linear_sequence), |
| stack["catalog"], |
| protected_positions=lead.protected_positions, |
| filters=stack["sampler"].filters, |
| ) |
|
|
|
|
| def property_free_supported_plan_view( |
| lead: Any, |
| initial_state: StapleState, |
| stack: dict[str, Any], |
| config: dict[str, Any], |
| ) -> dict[str, Any]: |
| """Build the one hard-constrained coarse-plan support used everywhere.""" |
| all_plans = legal_plans(lead, stack) |
| context = { |
| "protected_positions": lead.protected_positions, |
| "peptide_ca": (lead.target_context or {}).get("peptide_ca"), |
| } |
| all_reference_weights = stack["sampler"].plan_selection_weights( |
| initial_state, all_plans, context |
| ) |
| support_indices, verdicts = property_free_hard_plan_support( |
| initial_state=initial_state, |
| lead=lead, |
| plans=all_plans, |
| catalog=stack["catalog"], |
| catalog_index=stack["catalog_index"], |
| geometry=stack["geometry"], |
| config=config, |
| ) |
| return { |
| "all_plans": all_plans, |
| "all_reference_weights": all_reference_weights, |
| "support_indices": support_indices, |
| "plans": [all_plans[index] for index in support_indices], |
| |
| |
| "reference_weights": [ |
| all_reference_weights[index] for index in support_indices |
| ], |
| "verdicts": verdicts, |
| "context": context, |
| } |
|
|
|
|
| def plan_key(plan: Any) -> tuple[Any, ...]: |
| return (plan.ordered_pair, plan.spacing, tuple(plan.anchor_pair), plan.block_id) |
|
|
|
|
| def encode_lead(policy: Any, kernel: Any, state: StapleState) -> torch.Tensor: |
| features = state_to_features(state, kernel.block_to_idx) |
| device = kernel.device |
| features = {key: value.to(device) for key, value in features.items()} |
| with torch.no_grad(): |
| return policy.encoder(**features).detach() |
|
|
|
|
| def selected_top1_rates(selected: list[dict[str, Any]]) -> dict[str, float]: |
| n = max(len(selected), 1) |
| return { |
| "top1_chemistry_valid_rate": sum(bool(row["chemistry_valid"]) for row in selected) / n, |
| "top1_stapled_rate": sum(bool(row["stapled"]) for row in selected) / n, |
| } |
|
|
|
|
| def train_enabled_epoch( |
| leads: list[Any], |
| config: dict[str, Any], |
| stack: dict[str, Any], |
| energy_fn: Any, |
| policy: Any, |
| kernel: Any, |
| optimizer: Any, |
| parameters: list[torch.nn.Parameter], |
| head: HydrocarbonPlanHead, |
| plan_cfg: HydrocarbonPlanControlConfig, |
| plan_rng: random.Random, |
| epoch: int, |
| exact_sb_cache: Any = None, |
| ) -> tuple[list[dict[str, Any]], dict[str, Any]]: |
| train_cfg = config["training"] |
| horizon = int(train_cfg["horizon"]) |
| chunk_size = int(train_cfg["chunk_size"]) |
| rows_all: list[dict[str, Any]] = [] |
| losses: list[float] = [] |
| path_losses: list[float] = [] |
| plan_losses: list[float] = [] |
| entropies: list[float] = [] |
| coverage: list[float] = [] |
| disagreements: list[bool] = [] |
| exact_reverse_kls: list[float] = [] |
| exact_forward_objectives: list[float] = [] |
| exact_q_star_entropies: list[float] = [] |
| exact_plans_scored = 0 |
| joint_support_enabled = bool( |
| getattr( |
| getattr(energy_fn, "property_cfg", None), |
| "enable_joint_perm_halflife_support", |
| False, |
| ) |
| ) |
| joint_support_rows: list[dict[str, Any]] = [] |
| hard_mask_totals: Counter[str] = Counter() |
| exact_cache_sources: Counter[str] = Counter() |
| controlled_top_modes: Counter[str] = Counter() |
| weighting_totals: Counter[str] = Counter() |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| chunk_timing = bool((config.get("profiling") or {}).get("chunk_timing", False)) |
| _cuda_sync = chunk_timing and torch.cuda.is_available() |
|
|
| def _sync() -> None: |
| if _cuda_sync: |
| torch.cuda.synchronize() |
|
|
| STAGE_KEYS = ( |
| "plan_qtheta", "qstar_target", "fine_rollout", "neighbor_gen", |
| "terminal_pv", "policy_logprob", "backward", "optimizer", |
| ) |
| stage_seconds: dict[str, float] = {key: 0.0 for key in STAGE_KEYS} |
| _profiling_scorer = getattr(energy_fn, "property_scorer", None) |
| _pv_wrapper = getattr(_profiling_scorer, "predictor", None) |
| _esm2_prev = STAGE_TIMER.snapshot() |
| epoch_started = time.perf_counter() |
| total_leads = len(leads) |
|
|
| for chunk_start in range(0, len(leads), chunk_size): |
| chunk_leads = leads[chunk_start : chunk_start + chunk_size] |
| weighted_by_lead: list[list[WeightedTrajectory]] = [] |
| chunk_rows: list[dict[str, Any]] = [] |
| chunk_plan_losses: list[torch.Tensor] = [] |
| chunk_t: dict[str, float] = {key: 0.0 for key in STAGE_KEYS} |
| chunk_counts = { |
| "plans": 0, |
| "legal_plans_before_hard_mask": 0, |
| "hard_masked_plans": 0, |
| "leads_without_hard_support": 0, |
| "trajectories": 0, |
| "transitions": 0, |
| "neighbors": 0, |
| } |
| _cache_hits0 = exact_sb_cache.stats.hits if exact_sb_cache is not None else 0 |
| _cache_misses0 = exact_sb_cache.stats.misses if exact_sb_cache is not None else 0 |
| _pv_misses0 = _pv_wrapper.cache_misses if _pv_wrapper is not None else 0 |
| _pv_hits0 = _pv_wrapper.cache_hits if _pv_wrapper is not None else 0 |
| chunk_started = time.perf_counter() |
| for lead_index, lead in enumerate(chunk_leads, start=chunk_start): |
| lead_weighted: list[WeightedTrajectory] = [] |
| z0 = StapleState(sequence_tokens=tokenize_sequence(lead.linear_sequence)) |
| support_view = property_free_supported_plan_view( |
| lead, z0, stack, config |
| ) |
| all_plans = support_view["all_plans"] |
| support_indices = support_view["support_indices"] |
| plans = support_view["plans"] |
| ref_weights = support_view["reference_weights"] |
| context = support_view["context"] |
| chunk_counts["legal_plans_before_hard_mask"] += len(all_plans) |
| chunk_counts["plans"] += len(plans) |
| chunk_counts["hard_masked_plans"] += len(all_plans) - len(plans) |
| hard_mask_totals["legal_plans_before_hard_mask"] += len(all_plans) |
| hard_mask_totals["hard_supported_plans"] += len(plans) |
| hard_mask_totals["hard_masked_plans"] += len(all_plans) - len(plans) |
| if not plans: |
| chunk_counts["leads_without_hard_support"] += 1 |
| hard_mask_totals["leads_without_hard_support"] += 1 |
| if joint_support_enabled: |
| joint_support_rows.append( |
| { |
| "example_id": str(lead.example_id), |
| "n_hard_supported_plans": 0, |
| "joint_plan_count": 0, |
| "joint_nonempty": False, |
| "joint_fallback": False, |
| "q_star_support_size": 0, |
| "status": "no_hard_support", |
| } |
| ) |
| weighted_by_lead.append(lead_weighted) |
| continue |
| sampled = sample_distinct_plans( |
| plans, ref_weights, plan_cfg.plans_per_lead, plan_rng |
| ) |
| if not sampled: |
| raise RuntimeError(f"no sampled legal plan for {lead.example_id}") |
| key_to_index = {plan_key(plan): index for index, plan in enumerate(plans)} |
| _t = time.perf_counter() |
| lead_embedding = encode_lead(policy, kernel, z0) |
| all_controlled_logp = controlled_plan_log_probabilities( |
| head, |
| lead_embedding, |
| all_plans, |
| support_view["all_reference_weights"], |
| len(z0.sequence_tokens), |
| sequence_tokens=z0.sequence_tokens, |
| peptide_ca=context["peptide_ca"], |
| ) |
| masked_controlled_logp = mask_and_renormalize_plan_log_probabilities( |
| all_controlled_logp, support_indices |
| ) |
| controlled_logp = masked_controlled_logp[ |
| torch.tensor( |
| support_indices, |
| dtype=torch.long, |
| device=masked_controlled_logp.device, |
| ) |
| ] |
| chunk_t["plan_qtheta"] += time.perf_counter() - _t |
| joint_train_row: dict[str, Any] | None = None |
| if plan_cfg.exact_sb_objective: |
| reference_logp = empirical_log_probabilities( |
| ref_weights, controlled_logp.device |
| ) |
| |
| |
| |
| _t = time.perf_counter() |
| exact_energy_tensor, _, cache_info = resolve_exact_sb_target( |
| lead=lead, |
| plans=plans, |
| reference_log_probabilities=reference_logp, |
| beta=plan_cfg.exact_sb_beta, |
| energy_fn=energy_fn, |
| initial_state=z0, |
| build_terminal=lambda state, plan: build_hydrocarbon_demonstration_path( |
| state, plan, stack["catalog"] |
| )[-1], |
| cache=exact_sb_cache, |
| energy_only=energy_only_from_config(config), |
| ) |
| exact_cache_sources[str(cache_info["source"])] += 1 |
| target_support_mask = ( |
| torch.tensor( |
| cache_info["target_support_mask"], |
| dtype=torch.bool, |
| device=controlled_logp.device, |
| ) |
| if cache_info.get("target_support_mask") is not None |
| else None |
| ) |
| if joint_support_enabled: |
| joint_train_row = { |
| "example_id": str(lead.example_id), |
| "n_hard_supported_plans": len(plans), |
| "joint_plan_count": int(cache_info["joint_plan_count"]), |
| "joint_nonempty": bool(cache_info["joint_nonempty"]), |
| "joint_fallback": bool(cache_info["joint_fallback"]), |
| "q_star_support_size": int(cache_info["q_star_support_size"]), |
| "selection_semantics": "q_theta_top1_hard_plan", |
| "status": "scored", |
| } |
| joint_support_rows.append(joint_train_row) |
| chunk_t["qstar_target"] += time.perf_counter() - _t |
| _t = time.perf_counter() |
| exact_loss, forward_objective, log_q_star = configured_plan_level_objective( |
| controlled_logp, |
| [], |
| [], |
| plan_cfg.target_temperature, |
| exact_sb_objective=True, |
| reference_log_probabilities=reference_logp, |
| terminal_energies=exact_energy_tensor, |
| exact_sb_beta=plan_cfg.exact_sb_beta, |
| target_support_mask=target_support_mask, |
| ) |
| chunk_plan_losses.append(exact_loss) |
| exact_reverse_kls.append(float(exact_loss.detach().cpu().item())) |
| exact_forward_objectives.append( |
| float(forward_objective.detach().cpu().item()) |
| ) |
| q_star = log_q_star.exp() |
| if target_support_mask is None: |
| |
| q_star_entropy = -(q_star * log_q_star).sum() |
| else: |
| q_star_entropy = -torch.where( |
| q_star > 0.0, |
| q_star * log_q_star, |
| torch.zeros_like(q_star), |
| ).sum() |
| exact_q_star_entropies.append( |
| float(q_star_entropy.detach().cpu().item()) |
| ) |
| exact_plans_scored += len(plans) |
| chunk_t["plan_qtheta"] += time.perf_counter() - _t |
| reference_top = int(np.argmax(ref_weights)) |
| controlled_top = int(torch.argmax(controlled_logp).item()) |
| if joint_train_row is not None: |
| joint_train_row.update( |
| { |
| "selected_plan_index": controlled_top, |
| "selected_plan": describe_plan(plans[controlled_top]), |
| "selected_satisfies_joint_condition": bool( |
| target_support_mask is not None |
| and target_support_mask[controlled_top].item() |
| ), |
| } |
| ) |
| disagreements.append(reference_top != controlled_top) |
| entropies.append(float(plan_entropy(controlled_logp).detach().cpu().item())) |
| coverage.append(len(sampled) / len(plans)) |
| controlled_top_modes[ |
| f"{plans[controlled_top].ordered_pair}/i,i+{plans[controlled_top].spacing}" |
| ] += 1 |
|
|
| sampled_indices: list[int] = [] |
| penetrance_values: list[float] = [] |
| for trajectory_index, plan in enumerate(sampled): |
| _t = time.perf_counter() |
| trajectory = sample_committed_plan_trajectory( |
| stack["sampler"], |
| z0, |
| plan, |
| lead.protected_positions, |
| context, |
| horizon, |
| ) |
| chunk_t["fine_rollout"] += time.perf_counter() - _t |
| chunk_counts["trajectories"] += 1 |
| trajectory_context = {**context, "hydrocarbon_plan": plan} |
| steps: list[TransitionStep] = [] |
| for t, (state, next_state) in enumerate( |
| zip(trajectory.states[:-1], trajectory.states[1:]) |
| ): |
| _t = time.perf_counter() |
| candidates = stack["graph"].neighbors( |
| state, protected_positions=lead.protected_positions |
| ) |
| chunk_t["neighbor_gen"] += time.perf_counter() - _t |
| chunk_counts["neighbors"] += len(candidates) |
| chunk_counts["transitions"] += 1 |
| chosen = next( |
| (index for index, candidate in enumerate(candidates) if candidate == next_state), |
| None, |
| ) |
| if chosen is None: |
| raise RuntimeError("committed transition absent from graph") |
| steps.append(TransitionStep(state, next_state, candidates, chosen, t)) |
| terminal = trajectory.states[-1] |
| _t = time.perf_counter() |
| row = terminal_record( |
| z0, |
| terminal, |
| lead, |
| energy_fn, |
| stack, |
| epoch=epoch, |
| lead_index=lead_index, |
| trajectory_index=trajectory_index, |
| committed_plan=describe_plan(plan), |
| committed_plan_completed=trajectory.progress.plan_completed, |
| path_length=len(steps), |
| ) |
| chunk_t["terminal_pv"] += time.perf_counter() - _t |
| penetrance = row.get( |
| "hydrocarbon_permeability_penetrance_product_mean" |
| ) |
| penetrance_values.append(float(penetrance) if penetrance is not None else -1.0) |
| sampled_indices.append(key_to_index[plan_key(plan)]) |
| exact_completion = completes_committed_plan(terminal, plan) |
| failure_reason = ( |
| None |
| if exact_completion |
| else "off_plan_completion" |
| if terminal.topology == "stapled" |
| else "unfinished" |
| ) |
| row["trajectory_training_status"] = ( |
| "positive" if exact_completion else failure_reason |
| ) |
| lead_weighted.append( |
| WeightedTrajectory( |
| steps=steps, |
| terminal_state=terminal, |
| terminal_energy=float(row["terminal_energy"]), |
| context=trajectory_context, |
| is_positive=exact_completion, |
| failure_reason=failure_reason, |
| ) |
| ) |
| chunk_rows.append(row) |
| weighted_by_lead.append(lead_weighted) |
| if not plan_cfg.exact_sb_objective: |
| _t = time.perf_counter() |
| legacy_loss, _, _ = configured_plan_level_objective( |
| controlled_logp, |
| sampled_indices, |
| penetrance_values, |
| plan_cfg.target_temperature, |
| exact_sb_objective=False, |
| ) |
| chunk_plan_losses.append(legacy_loss) |
| chunk_t["plan_qtheta"] += time.perf_counter() - _t |
|
|
| weight_diagnostics = assign_lead_local_positive_weights(weighted_by_lead) |
| for key in ("n_positive", "n_failure", "n_leads_without_positive"): |
| weighting_totals[key] += int(weight_diagnostics[key]) |
| weighted = [ |
| trajectory for group in weighted_by_lead for trajectory in group |
| ] |
| if not chunk_plan_losses: |
| rows_all.extend(chunk_rows) |
| continue |
| _sync() |
| _t = time.perf_counter() |
| log_probs = [ |
| kernel.log_prob_of( |
| step.state, |
| step.candidates, |
| step.chosen_idx, |
| step.t, |
| trajectory.context, |
| ) |
| for trajectory in weighted |
| for step in trajectory.steps |
| ] |
| path_loss = compute_weighted_path_loss(weighted, log_probs) |
| plan_loss = torch.stack(chunk_plan_losses).mean() |
| total_loss = path_loss + float(plan_cfg.loss_weight) * plan_loss |
| _sync() |
| chunk_t["policy_logprob"] += time.perf_counter() - _t |
| optimizer.zero_grad() |
| _t = time.perf_counter() |
| total_loss.backward() |
| _sync() |
| chunk_t["backward"] += time.perf_counter() - _t |
| _t = time.perf_counter() |
| torch.nn.utils.clip_grad_norm_( |
| parameters, float(train_cfg.get("grad_clip_norm", 1.0)) |
| ) |
| optimizer.step() |
| _sync() |
| chunk_t["optimizer"] += time.perf_counter() - _t |
| losses.append(float(total_loss.detach().cpu().item())) |
| path_losses.append(float(path_loss.detach().cpu().item())) |
| plan_losses.append(float(plan_loss.detach().cpu().item())) |
| rows_all.extend(chunk_rows) |
|
|
| for key in STAGE_KEYS: |
| stage_seconds[key] += chunk_t[key] |
| if chunk_timing: |
| _esm2_now = STAGE_TIMER.snapshot() |
| esm2_diff = { |
| key: _esm2_now.get(key, 0) - _esm2_prev.get(key, 0) |
| for key in ( |
| "esm2_forward_time", "esm2_cache_hit", "esm2_cache_miss", |
| "esm2_forward_batches", "esm2_forward_calls", |
| ) |
| } |
| _esm2_prev = _esm2_now |
| leads_done = chunk_start + len(chunk_leads) |
| elapsed = time.perf_counter() - epoch_started |
| leads_per_min = leads_done / (elapsed / 60.0) if elapsed > 0 else 0.0 |
| eta_seconds = ( |
| (elapsed / leads_done) * (total_leads - leads_done) if leads_done else 0.0 |
| ) |
| record = { |
| "epoch": epoch + 1, |
| "chunk": chunk_start // chunk_size + 1, |
| "leads_done": leads_done, |
| "total_leads": total_leads, |
| "chunk_seconds": round(time.perf_counter() - chunk_started, 3), |
| "stage_seconds": {key: round(chunk_t[key], 4) for key in STAGE_KEYS}, |
| "esm2": { |
| key: (round(value, 4) if "time" in key else int(value)) |
| for key, value in esm2_diff.items() |
| }, |
| "counts": dict(chunk_counts), |
| "exact_sb_cache": { |
| "hits": (exact_sb_cache.stats.hits - _cache_hits0) |
| if exact_sb_cache is not None else 0, |
| "misses": (exact_sb_cache.stats.misses - _cache_misses0) |
| if exact_sb_cache is not None else 0, |
| }, |
| "peptiverse": { |
| "predictions": (_pv_wrapper.cache_misses - _pv_misses0) |
| if _pv_wrapper is not None else 0, |
| "cache_hits": (_pv_wrapper.cache_hits - _pv_hits0) |
| if _pv_wrapper is not None else 0, |
| }, |
| "leads_per_min": round(leads_per_min, 1), |
| "epoch_eta_min": round(eta_seconds / 60.0, 1), |
| } |
| print(f"[chunk timing] {json.dumps(record, ensure_ascii=False)}", flush=True) |
|
|
|
|
| metrics = { |
| "loss": float(np.mean(losses)), |
| "path_loss": float(np.mean(path_losses)), |
| "plan_loss": float(np.mean(plan_losses)), |
| "plan_entropy": float(np.mean(entropies)), |
| "plan_coverage": float(np.mean(coverage)), |
| "reference_vs_controlled_plan_disagreement": float(np.mean(disagreements)), |
| "controlled_plan_mode_mix": dict(controlled_top_modes), |
| "exact_sb_objective": bool(plan_cfg.exact_sb_objective), |
| "exact_sb_beta": float(plan_cfg.exact_sb_beta), |
| "plan_encoder_v2": bool(plan_cfg.plan_encoder_v2), |
| "legacy_target_temperature": float(plan_cfg.target_temperature), |
| "legacy_property_only_equivalent_beta": float( |
| 1.0 |
| / ( |
| plan_cfg.target_temperature |
| * float( |
| config["hydrocarbon"]["terminal_energy"]["property"][ |
| "penetrance_weight" |
| ] |
| ) |
| ) |
| ), |
| "q_star_vs_q_theta_kl": ( |
| float(np.mean(exact_reverse_kls)) if exact_reverse_kls else None |
| ), |
| "exact_sb_forward_objective": ( |
| float(np.mean(exact_forward_objectives)) |
| if exact_forward_objectives |
| else None |
| ), |
| "q_star_entropy": ( |
| float(np.mean(exact_q_star_entropies)) |
| if exact_q_star_entropies |
| else None |
| ), |
| "exact_sb_plans_scored": int(exact_plans_scored), |
| "exact_sb_target_sources": dict(exact_cache_sources), |
| "property_free_hard_plan_mask": True, |
| "hard_plan_mask_uses_peptiverse": False, |
| "hard_plan_mask_totals": dict(hard_mask_totals), |
| "trajectory_weighting": { |
| "normalization": "lead_local_positive_only", |
| **{key: int(value) for key, value in weighting_totals.items()}, |
| }, |
| "stage_seconds": {key: float(value) for key, value in stage_seconds.items()}, |
| } |
| if joint_support_enabled: |
| supported_joint_rows = [ |
| row for row in joint_support_rows if row["status"] == "scored" |
| ] |
| solution_leads = sum( |
| bool(row["joint_nonempty"]) for row in supported_joint_rows |
| ) |
| selected_joint = sum( |
| bool(row["selected_satisfies_joint_condition"]) |
| for row in supported_joint_rows |
| ) |
| metrics["joint_perm_halflife_support"] = { |
| "enabled": True, |
| "leads_total": len(joint_support_rows), |
| "leads_with_hard_support": len(supported_joint_rows), |
| "leads_without_hard_support": sum( |
| row["status"] == "no_hard_support" for row in joint_support_rows |
| ), |
| "leads_with_joint_solution": solution_leads, |
| "fallback_leads": sum( |
| bool(row["joint_fallback"]) for row in supported_joint_rows |
| ), |
| "joint_plan_count": sum( |
| int(row["joint_plan_count"]) for row in supported_joint_rows |
| ), |
| "q_star_support_size": sum( |
| int(row["q_star_support_size"]) for row in supported_joint_rows |
| ), |
| "selected_joint_solutions": selected_joint, |
| "joint_solution_recovery": ( |
| selected_joint / solution_leads if solution_leads else None |
| ), |
| "per_lead": joint_support_rows, |
| } |
| return rows_all, metrics |
|
|
|
|
| @torch.no_grad() |
| def validate_enabled( |
| leads: list[Any], |
| config: dict[str, Any], |
| stack: dict[str, Any], |
| energy_fn: Any, |
| policy: Any, |
| kernel: Any, |
| head: HydrocarbonPlanHead, |
| exact_sb_cache: Any = None, |
| ) -> tuple[list[dict[str, Any]], dict[str, Any]]: |
| validation_cfg = config["validation"] |
| selected: list[dict[str, Any]] = [] |
| entropies: list[float] = [] |
| coverages: list[float] = [] |
| disagreements: list[bool] = [] |
| top1_plans: dict[str, str] = {} |
| mode_mix: Counter[str] = Counter() |
| |
| |
| |
| exact_sb_diagnostics = exact_sb_validation_enabled(config) |
| exact_sb_beta = HydrocarbonPlanControlConfig.from_config(config).exact_sb_beta |
| q_star_rows: list[dict[str, Any]] = [] |
| q_star_cache_sources: Counter[str] = Counter() |
| joint_support_enabled = bool( |
| getattr( |
| getattr(energy_fn, "property_cfg", None), |
| "enable_joint_perm_halflife_support", |
| False, |
| ) |
| ) |
| joint_support_rows: list[dict[str, Any]] = [] |
| legal_plans_before_hard_mask = 0 |
| hard_supported_plans = 0 |
| leads_without_hard_support = 0 |
| |
| q_star_diagnostics_seconds = 0.0 |
|
|
| for lead_index, lead in enumerate(leads): |
| z0 = StapleState(sequence_tokens=tokenize_sequence(lead.linear_sequence)) |
| support_view = property_free_supported_plan_view(lead, z0, stack, config) |
| all_plans = support_view["all_plans"] |
| support_indices = support_view["support_indices"] |
| plans = support_view["plans"] |
| ref_weights = support_view["reference_weights"] |
| context = support_view["context"] |
| legal_plans_before_hard_mask += len(all_plans) |
| hard_supported_plans += len(plans) |
| strict_support_at_lead = bool(plans) |
| if not plans: |
| leads_without_hard_support += 1 |
| if joint_support_enabled: |
| joint_support_rows.append( |
| { |
| "example_id": str(lead.example_id), |
| "n_hard_supported_plans": 0, |
| "joint_plan_count": 0, |
| "joint_nonempty": False, |
| "joint_fallback": False, |
| "q_star_support_size": 0, |
| "selected_satisfies_joint_condition": False, |
| "status": "no_hard_support", |
| } |
| ) |
| print( |
| f"[plan validation] leads={lead_index + 1}/{len(leads)} " |
| "status=no_strict_feasible_plan", |
| flush=True, |
| ) |
| continue |
| lead_embedding = encode_lead(policy, kernel, z0) |
| all_controlled_logp = controlled_plan_log_probabilities( |
| head, |
| lead_embedding, |
| all_plans, |
| support_view["all_reference_weights"], |
| len(z0.sequence_tokens), |
| sequence_tokens=z0.sequence_tokens, |
| peptide_ca=context["peptide_ca"], |
| ) |
| masked_controlled_logp = mask_and_renormalize_plan_log_probabilities( |
| all_controlled_logp, support_indices |
| ) |
| controlled_logp = masked_controlled_logp[ |
| torch.tensor( |
| support_indices, |
| dtype=torch.long, |
| device=masked_controlled_logp.device, |
| ) |
| ] |
| controlled_probabilities = controlled_logp.detach().exp().cpu() |
| plan_modes = [plan_mode(plan) for plan in plans] |
| q_theta_metrics = { |
| "q_theta_entropy": float(plan_entropy(controlled_logp).cpu().item()), |
| "q_theta_top1_mode": plan_modes[int(torch.argmax(controlled_logp).item())], |
| "q_theta_s5_s5_i4_probability_mass": float( |
| sum( |
| controlled_probabilities[index].item() |
| for index, mode in enumerate(plan_modes) |
| if mode == "S5-S5/i,i+4" |
| ) |
| ), |
| "q_theta_r8_s5_i7_probability_mass": float( |
| sum( |
| controlled_probabilities[index].item() |
| for index, mode in enumerate(plan_modes) |
| if mode == "R8-S5/i,i+7" |
| ) |
| ), |
| } |
| entropies.append(float(plan_entropy(controlled_logp).cpu().item())) |
| reference_top = int(np.argmax(ref_weights)) |
| controlled_top = int(torch.argmax(controlled_logp).item()) |
| disagreements.append(reference_top != controlled_top) |
| coverages.append(1.0) |
|
|
| lead_q_star_row: dict[str, Any] | None = None |
| if exact_sb_diagnostics: |
| _diagnostics_started = time.perf_counter() |
| reference_logp = empirical_log_probabilities( |
| ref_weights, controlled_logp.device |
| ) |
| |
| |
| plan_energy_tensor, _, cache_info = resolve_exact_sb_target( |
| lead=lead, |
| plans=plans, |
| reference_log_probabilities=reference_logp, |
| beta=exact_sb_beta, |
| energy_fn=energy_fn, |
| initial_state=z0, |
| build_terminal=lambda state, plan: build_hydrocarbon_demonstration_path( |
| state, plan, stack["catalog"] |
| )[-1], |
| cache=exact_sb_cache, |
| energy_only=energy_only_from_config(config), |
| ) |
| q_star_cache_sources[str(cache_info["source"])] += 1 |
| target_support_mask = ( |
| torch.tensor( |
| cache_info["target_support_mask"], |
| dtype=torch.bool, |
| device=controlled_logp.device, |
| ) |
| if cache_info.get("target_support_mask") is not None |
| else None |
| ) |
| diagnostics = lead_q_star_diagnostics( |
| controlled_logp, |
| reference_logp, |
| plan_energy_tensor, |
| exact_sb_beta, |
| plan_modes=plan_modes, |
| target_support_mask=target_support_mask, |
| ) |
| lead_q_star_row = { |
| "example_id": str(lead.example_id), |
| "q_star_top1_plan": describe_plan( |
| plans[diagnostics["q_star_top1_index"]] |
| ), |
| "q_theta_top1_plan": describe_plan( |
| plans[diagnostics["q_theta_top1_index"]] |
| ), |
| "joint_perm_halflife_support_enabled": bool( |
| cache_info["joint_perm_halflife_support_enabled"] |
| ), |
| "joint_plan_count": cache_info["joint_plan_count"], |
| "joint_nonempty": cache_info["joint_nonempty"], |
| "joint_fallback": cache_info["joint_fallback"], |
| "q_star_support_size": int(cache_info["q_star_support_size"]), |
| **diagnostics, |
| } |
| q_star_rows.append(lead_q_star_row) |
| q_star_diagnostics_seconds += time.perf_counter() - _diagnostics_started |
|
|
| hierarchical = hierarchical_plan_ranking_enabled(config) |
| decoded_by_plan: list[tuple[StapleState, float, int] | None] = [None] * len(plans) |
| decode_indices = [controlled_top] if hierarchical else range(len(plans)) |
| for plan_index in decode_indices: |
| plan = plans[plan_index] |
| decoded = beam_decode( |
| lead, |
| stack, |
| kernel, |
| int(validation_cfg["horizon"]), |
| int(validation_cfg["beam_size"]), |
| committed_plan=plan, |
| ) |
| if decoded: |
| decoded_by_plan[plan_index] = ( |
| best_committed_plan_trajectory(decoded, plan) if hierarchical else decoded[0] |
| ) |
| try: |
| joint, plan_index, terminal, path_logp, path_length = select_plan_and_trajectory( |
| controlled_logp.detach().cpu(), decoded_by_plan, hierarchical=hierarchical |
| ) |
| except RuntimeError as exc: |
| raise RuntimeError(f"no decoded plans for {lead.example_id}") from exc |
| selected_plan = plans[plan_index] |
| label = describe_plan(selected_plan) |
| top1_plans[lead.example_id] = label |
| mode_mix[ |
| f"{selected_plan.ordered_pair}/i,i+{selected_plan.spacing}" |
| ] += 1 |
| selected_record = terminal_record( |
| z0, |
| terminal, |
| lead, |
| energy_fn, |
| stack, |
| lead_index=lead_index, |
| committed_plan=label, |
| plan_log_probability=float(controlled_logp[plan_index].cpu().item()), |
| path_log_probability=path_logp, |
| joint_log_probability=joint, |
| path_length=path_length, |
| ) |
| selected.append(selected_record) |
|
|
| print(f"[plan validation] leads={lead_index + 1}/{len(leads)}", flush=True) |
|
|
| summary = summarize(selected, selected, len(leads)) |
| summary.update(selected_top1_rates(selected)) |
| summary.update( |
| { |
| "plan_control_enabled": True, |
| "hierarchical_plan_ranking": hierarchical_plan_ranking_enabled(config), |
| "plan_entropy": float(np.mean(entropies)) if entropies else None, |
| "plan_top1": top1_plans, |
| "plan_coverage": float(np.mean(coverages)) if coverages else 0.0, |
| "mode_mix": dict(mode_mix), |
| "reference_vs_controlled_plan_disagreement": ( |
| float(np.mean(disagreements)) if disagreements else None |
| ), |
| "property_free_hard_plan_mask": True, |
| "hard_plan_mask_uses_peptiverse": False, |
| "legal_plans_before_hard_mask": int(legal_plans_before_hard_mask), |
| "hard_supported_plans": int(hard_supported_plans), |
| "hard_masked_plans": int( |
| legal_plans_before_hard_mask - hard_supported_plans |
| ), |
| "leads_without_hard_support": int(leads_without_hard_support), |
| } |
| ) |
| summary["exact_sb_validation_diagnostics"] = exact_sb_diagnostics |
| if exact_sb_diagnostics: |
| |
| summary.update(aggregate_q_star_diagnostics(q_star_rows)) |
| summary["q_star_per_lead"] = q_star_rows |
| |
| summary["q_star_target_sources"] = dict(q_star_cache_sources) |
| summary["q_star_diagnostics_seconds"] = float(q_star_diagnostics_seconds) |
| if joint_support_enabled: |
| supported_joint_rows = [ |
| row for row in joint_support_rows if row["status"] == "scored" |
| ] |
| solution_leads = sum( |
| bool(row["joint_nonempty"]) for row in supported_joint_rows |
| ) |
| selected_joint = sum( |
| bool(row["selected_satisfies_joint_condition"]) |
| for row in supported_joint_rows |
| ) |
| summary["joint_perm_halflife_support"] = { |
| "enabled": True, |
| "leads_total": len(joint_support_rows), |
| "leads_with_hard_support": len(supported_joint_rows), |
| "leads_without_hard_support": sum( |
| row["status"] == "no_hard_support" for row in joint_support_rows |
| ), |
| "leads_with_joint_solution": solution_leads, |
| "fallback_leads": sum( |
| bool(row["joint_fallback"]) for row in supported_joint_rows |
| ), |
| "joint_plan_count": sum( |
| int(row["joint_plan_count"]) for row in supported_joint_rows |
| ), |
| "q_star_support_size": sum( |
| int(row["q_star_support_size"]) for row in supported_joint_rows |
| ), |
| "selected_joint_solutions": selected_joint, |
| "joint_solution_recovery": ( |
| selected_joint / solution_leads if solution_leads else None |
| ), |
| "per_lead": joint_support_rows, |
| } |
| return selected, summary |
|
|