Geometry and structural losses · INTEGRATION
Symmetry assignment: rigid fits and ambiguous atom renaming
AlphaFold2AlphaFold3AlphaFold-MultimerOpenFold
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Your task
Score each supplied admissible target permutation using the selected geometric objective. Choose the lowest-cost labeling with the declared tie rule and return the matched target and fit diagnostics.
Function signature
symmetry_permutation_alignment(
pred: torch.Tensor,
target: torch.Tensor,
weights: torch.Tensor,
mask: torch.Tensor,
permutations: torch.Tensor,
ambiguous: torch.Tensor | None = None,
rename_group: torch.Tensor | None = None,
objective: str = 'rigid_mse',
distance_eps: float = 1e-10,
error_eps: float = 1e-10,
) -> dict[str, torch.Tensor]Worked example
A labeling swap changes anchor distances
For objective="ambiguous_distance", take target atoms [(1,0,0),(3,0,0),(0,0,0)] and prediction atoms [(3,0,0),(1,0,0),(0,0,0)]. All three atoms are observed with unit weights. Set ambiguous=rename_group=[True,True,False], and supply candidates [0,1,2] and [1,0,2]; use distance_eps=error_eps=1e-10. Only ambiguous atoms 0 and 1 are compared with anchor 2. Identity mismatches distances near 1 and 3 twice, giving cost approximately 4. The swapped candidate matches both regularized distances exactly, giving cost 2·sqrt(1e-10)=0.00002. Select index 1 and its swapped target coordinates; rotation is identity and translation is zero because this objective does no rigid fitting.
Parameters
| Parameter | Shape and meaning |
|---|---|
predtorch.Tensor | [B, N, 3]Predicted coordinates in prediction-slot order |
targettorch.Tensor | [B, N, 3]Reference coordinates before label assignment |
weightstorch.Tensor | [B, N]Positive on observed prediction slots |
masktorch.Tensor | [B, N]Common support preserved by every permutation |
permutationstorch.Tensor | [B, K, N]Candidate target-index mappings: permutations[b,k,i] is the target slot matched to prediction slot i. |
ambiguoustorch.Tensor | NoneDefault None | [B, N]Required in ambiguous_distance mode: all ambiguous atom slots, including atoms outside the queried rename group. |
rename_grouptorch.Tensor | NoneDefault None | [B, N]Required in ambiguous_distance mode: the group whose ambiguous atom names may change. |
objectivestrDefault 'rigid_mse' | Choose "rigid_mse", "ambiguous_distance". objective='rigid_mse' (default): For each b,k solve \min_{R\in\mathrm{SO}(3),\,t}\frac{\sum_i w_i\|R\,\texttt{target}_{p_k(i)}+t-\texttt{pred}_i\|^2}{\sum_i w_i}. |
distance_epsfloatDefault 1e-10 | Positive offset inside squared-distance square roots in ambiguous-distance mode; it does not alter the rigid-MSE objective. |
error_epsfloatDefault 1e-10 | Positive offset inside \sqrt{(d_{\mathrm{pred}}-d_{\mathrm{target}})^2+\varepsilon_{\mathrm{error}}} in ambiguous-distance mode. |
Return
dict[str, torch.Tensor]
Return exactly the named fields applicable to this operation.
Required behavior
- For
B\ge 1batches,N\ge 0points andK\ge 1supplied admissiblepermutations, select the best permuted TARGET against the PREDICTION.pred,targetare[B,N,3],weights[B,N],mask[B,N],permutations[B,K,N].permutations[b,k,i]gives thetargetindex matched to prediction sloti. - Every candidate is a bijection of0..
N-1, already checked for chemical/chain admissibility, and preservesmask:\mathrm{mask}[b,\mathrm{permutations}[b,k,i]]=\mathrm{mask}[b,i]. Thus candidates cannot win by discarding observations. - Weights are finite positive at observed slots, arbitrary finite at masked slots; effective
w=\operatorname{where}(\mathrm{mask},\mathrm{weights},0). Masked coordinates may be nonfinite and must be sanitized before arithmetic. objective='rigid_mse'(default): For eachb,ksolve\min_{R\in\mathrm{SO}(3),\,t}\frac{\sum_i w_i\|R\,\texttt{target}_{p_k(i)}+t-\texttt{pred}_i\|^2}{\sum_i w_i}. Rotation uses COLUMN vectors.- Center the two clouds with the SAME prediction-slot
weightsand formH=\sum_{i} w_{i}(\mathrm{target\_p}(i)-\mu_{x})(\mathrm{pred\_i}-\mu_{y})^{\top}. The narrowtorch.linalg.svdcall is allowed, but implement centering, covariance, determinant/reflection correction,translationand loss yourself. Reflection is not an allowedrotation. matched_targetis the selected rotated/translatedtargetat observed slots and0 at masked slots; return that selectedR,t. Cost has units of squared angstroms.objective='ambiguous_distance': additionally receiveambiguous[B,N] (all chemicallyambiguousatoms, including those outside the queried group) andrename_group[B,N] (the residue/group whose naming is being chosen). Candidates may change only indices that are BOTHambiguousand inrename_group; every other index stays fixed.- Define
\mathrm{dp\_ij}=\sqrt{\mathrm{distance\_eps}+\Vert \mathrm{pred\_i}-\mathrm{pred\_j}\Vert ^{2}}and\mathrm{dt\_kij}=\sqrt{\mathrm{distance\_eps}+\Vert \mathrm{target\_p\_k}(i)-\mathrm{target\_p\_k}(j)\Vert ^{2}}. - Candidate
costisSUM_ijw_{i}\cdot w_{j}\cdot A_{\mathrm{ij}}\cdot \sqrt{\mathrm{error\_eps}+(\mathrm{dp\_ij}-\mathrm{dt\_kij})^{2}}, whereA_{\mathrm{ij}}=\mathrm{ambiguous\_i}ANDrename_group_iAND notambiguous_j. This is a SUM, not a mean, squared error or rigid-aligned RMSD. - Unit
weightsreproduce the maskedambiguous-to-unambiguous comparison in AF2\mathrm{Algorithm26}/\mathrm{OpenFold}; extraambiguousatoms elsewhere are not fixed anchors. Both epsilons default10^{-10}, matching that common source convention. - Their locations are independent: distance regularization versus absolute-error regularization. Perfect matching still has the explicit
\sqrt{\mathrm{error\_eps}}floor for each selected pair. No eligible pairs gives0. This mode does not use SVD or require a nondegenerate cloud. matched_targetis the selected renamedtargetwithout geometric fitting; returnedR=\mathrm{identity},t=0. Cost has weighted angstrom-error units, not squared-distance units. Returncandidate_cost[B,K] and choose the FIRST minimum candidate per batch.- Return selected
cost,matched_target[B,N,3],rotation[B,3,3],translation[B,3],permutation[B,N],permutation_index[B]. Selection is exact only within the SUPPLIED candidate set. - It does not solve chemical graph isomorphism, unconstrained factorial chain assignment, Hungarian matching or upstream greedy-anchor candidate discovery. Do not choose independent
permutationsfor different downstream losses. - For
rigid_msethe supported numerical domain is either no observations (includingN=0), or positive observedweightswith every candidate's weighted centered covariance full rank and having distinct positive singular values. Nonempty rank-deficient/repeated-singular-value fits are outside that mode's contract. - Smooth selection fixtures have a unique winner. With no observations either mode returns candidate costs0, index0, identity
R,zerotand zero/empty matched coordinates. Duplicate candidates choose the first; no derivative is claimed at a general changing-assignment boundary. - Empty
B/K, unknown objective, or nonpositivedistance_eps/error_epsraiseValueError; other shape/domain violations are outside the contract. The continuous costs and selected transform remain differentiable on smooth branches, including zero VJPs for absent observations. - Chemical tables, candidate enumeration and experimental coordinate acquisition are supplied resources.
Why this matters
Equivalent atom or chain labels can describe the same structure. This task compares an already-supplied candidate set; it does not infer chemical equivalence or search every possible assignment.
Starter code
You write the body of this function in the BioTorch workspace. Your code runs in an isolated PyTorch sandbox; Run checks the public examples and Submit grades the full test suite, including gradients.
import torch
def symmetry_permutation_alignment(
pred: torch.Tensor, # (B, N, 3)
target: torch.Tensor, # (B, N, 3)
weights: torch.Tensor, # (B, N)
mask: torch.Tensor, # (B, N)
permutations: torch.Tensor, # (B, K, N)
ambiguous: torch.Tensor | None = None, # (B, N)
rename_group: torch.Tensor | None = None, # (B, N)
objective: str = 'rigid_mse',
distance_eps: float = 1e-10,
error_eps: float = 1e-10,
) -> dict[str, torch.Tensor]:
"""Return dict[str, torch.Tensor]:
candidate_cost: (B, K).
cost: (B,).
matched_target: (B, N, 3).
rotation: (B, 3, 3).
translation: (B, 3).
permutation_index: (B,).
permutation: (B, N)."""
# Implement the operation. Inputs and test setup are supplied by BioTorch.
raise NotImplementedError("Implement symmetry_permutation_alignment")
Ready to implement it?
3 progressive hints, a solution walkthrough, and grading that checks values, shapes and gradients are waiting in the workspace.
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Related exercises
Sources and further reading
A primitive exercise, not an end-to-end reproduction of the named models. No affiliation or endorsement is implied.