Geometry and structural losses
Ambiguous Atom Renaming
AlphaFold2AlphaFold-MultimerOpenFold
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Your task
Choose the best supplied admissible atom permutation using its distances from ambiguous atoms to unambiguous anchors.
Function signature
ambiguous_atom_renaming(
pred: torch.Tensor,
target: torch.Tensor,
weights: torch.Tensor,
mask: torch.Tensor,
permutations: torch.Tensor,
ambiguous: torch.Tensor,
rename_group: torch.Tensor,
distance_eps: float = 1e-10,
error_eps: float = 1e-10,
) -> dict[str, torch.Tensor]Worked example
Choose a swap from anchor distances
Atoms 0 and 1 are ambiguous; atom 2 is a fixed anchor at the origin. Target-to-anchor distances are [1, 3], while prediction-to-anchor distances are [3, 1]. The identity assignment mismatches both distances by 2; swapping atoms 0 and 1 makes both agree. Choose candidate 1. Its regularized cost retains a small epsilon floor even at exact agreement.
import torch
pred = torch.tensor([[[3.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]], dtype=torch.float64, requires_grad=True)
target = torch.tensor([[[1.0, 0.0, 0.0], [3.0, 0.0, 0.0], [0.0, 0.0, 0.0]]], dtype=torch.float64, requires_grad=True)
weights = torch.tensor([[1.0, 1.0, 1.0]], dtype=torch.float64, requires_grad=True)
mask = torch.tensor([[True, True, True]], dtype=torch.bool)
permutations = torch.tensor([[[0, 1, 2], [1, 0, 2]]], dtype=torch.int64)
ambiguous = torch.tensor([[True, True, False]], dtype=torch.bool)
rename_group = torch.tensor([[True, True, False]], dtype=torch.bool)
distance_eps = 1e-10
error_eps = 1e-10
result = ambiguous_atom_renaming(pred=pred, target=target, weights=weights, mask=mask, permutations=permutations, ambiguous=ambiguous, rename_group=rename_group, distance_eps=distance_eps, error_eps=error_eps)Expected return
{
'candidate_cost': torch.tensor([[3.9999999999833333, 2e-05]], dtype=torch.float64),
'cost': torch.tensor([2e-05], dtype=torch.float64),
'matched_target': torch.tensor([[[3.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]], dtype=torch.float64),
'rotation': torch.tensor([[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]], dtype=torch.float64),
'translation': torch.tensor([[0.0, 0.0, 0.0]], dtype=torch.float64),
'permutation_index': torch.tensor([1], dtype=torch.int64),
'permutation': torch.tensor([[1, 0, 2]], dtype=torch.int64),
}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]Nonnegative per-atom weights; only observed slots contribute. |
masktorch.Tensor | [B, N]Common support preserved by every permutation. |
permutationstorch.Tensor | [B, K, N]Admissible bijections; target[p[i]] matches prediction i. |
ambiguoustorch.Tensor | [B, N]True for every atom with ambiguous naming, including atoms outside the group being renamed. |
rename_grouptorch.Tensor | [B, N]True for ambiguous source atoms in the group whose naming is being selected. |
distance_epsfloatDefault 1e-10 | Positive offset inside each squared-distance square root; defaults to 1e-10. |
error_epsfloatDefault 1e-10 | Epsilon used in an error norm. |
Return
dict[str, torch.Tensor]
Return exactly the named fields applicable to this operation.
Required behavior
- pred/target are
[B,N,3]; permutations is[B,K,N], with K positive. Each candidate maps target coordinates as target[permutation]. Supplied permutations preserve chemical admissibility and mask validity; do not search for additional permutations. - Mask excluded coordinates before computing candidates. weights is a nonnegative per-atom weight and contributes only where mask=True.
- Compute stabilized pair distances
\sqrt{\|r_i-r_j\|^2+distance\_eps}, then error\sqrt{(d^{pred}_{ij}-d^{target}_{ij})^2+error\_eps}. Both epsilons default to10^{-10}and are positive. - Sum errors with weights_i × weights_j only where ambiguous[i] AND rename_group[i] AND NOT ambiguous[j]. This is a SUM, without dividing by weight or pair count. Do not rigidly align in this objective; rotation is identity, translation zero, and matched_target is the chosen permuted target.
- Pick the first candidate with the minimum cost. Return all candidate costs, selected cost/index/permutation, and selected matched coordinates/frame. Rotation uses column-vector form: matched = target @ rotation.T + translation.
- Selection is discrete, but keep gradients through the selected candidate’s floating computation. Do not mutate coordinates or modify supplied permutations.
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 ambiguous_atom_renaming(
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, # (B, N)
rename_group: torch.Tensor, # (B, N)
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 ambiguous_atom_renaming")
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.