Protein sequence and inverse folding

Constrained categorical sampling with tied positions

HardRaw PyTorchAbout 30 min2 public examples plus private tests

ProteinMPNNESM3Evo 1ProGen2

Write and run your solution Sign in

Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.

Your task

Select one consistent token identity for each tied-position group under supplied class restrictions. Apply the configured filters and temperature, then return sampled tokens and their probability diagnostics.

Function signature

constrained_categorical_sampling(
    logits: torch.Tensor,
    temperature: torch.Tensor,
    uniform: torch.Tensor,
    tokens: torch.Tensor,
    group_ids: torch.Tensor,
    allowed: torch.Tensor,
    parameters: dict,
    masks: dict,
    top_k: int = 0,
    top_p: float = 1.0,
    filter_order: str = 'before_temperature',
    nucleus_rule: str = 'standard',
) -> dict[str, torch.Tensor]

Worked example

Unequal member weights and intersected legal classes

Two editable positions belong to group 0. Class 1 is forbidden by the first member, leaving classes 0 and 2. Each member gives class 2 score \log3, and their weights are 1 and 3. Divide the weighted sum by two active members: class 2’s group score is (\log3+3\log3)/2=\log9; class 0’s is zero. Temperature 1 gives probabilities [0.1, 0, 0.9]. Uniform 0.75 passes class 0’s cumulative 0.1 and crosses at class 2, so both tokens become 2 and log_probability is \log0.9.

Parameters

ParameterShape and meaning
logitstorch.Tensor[B, L, V]Unnormalized vocabulary scores for every sequence position.
temperaturetorch.Tensor[B, G]Nonnegative floating [B,G]; \mathrm{zero}=\mathrm{greedy}.
uniformtorch.Tensor[B, G]Supplied floating [B,G] in [0,1), discrete random variates.
tokenstorch.Tensor[B, L]Integer current [B,L].
group_idstorch.Tensor[B, L]Only valid-position IDs must be in range.
allowedtorch.Tensor[B, L, V]True means legal class.
parametersdictSupplied model parameters, keyed as shown below.
masksdictSupplied masks. Each field below defines what True includes or permits.
top_kintDefault 0Keep at most this many allowed classes by stable score rank. Zero disables top-k; a positive value must not exceed vocabulary size.
top_pfloatDefault 1.0Nucleus probability threshold in (0,1]. One disables nucleus truncation; apply it after any top-k restriction.
filter_orderstrDefault 'before_temperature'Choose "before_temperature" to filter original group scores or "after_temperature" to filter temperature-scaled scores.
nucleus_rulestrDefault 'standard'"standard" keeps the first class crossing the threshold; "esm3" keeps only classes whose cumulative mass is at most the threshold, always retaining the top class.

Return

dict[str, torch.Tensor]

Return exactly the named fields applicable to this operation.

Required behavior

  • logits and bias are finite floating [B,L,V], \mathrm{weights}[B,L]\ge 0, \mathrm{temperature}[B,G]\ge 0; B,G\ge 1,L\ge 0,V\ge 2. uniform [B,G] is supplied in [0,1), never drawn internally. All floats share dtype/device; all scaled scores/differences must be representable.
  • group_ids [B,L] is in [0,G) on valid positions (arbitrary integers on padding). valid_mask,update_mask are bool [B,L]; allowed [B,L,V] uses True means legal class. tokens [B,L] are current integers: valid non-updated positions must have IDs in [0,V), while update/padding slots may carry arbitrary placeholders.
  • For group g, members are valid positions with that group ID and active members additionally have update_mask=True. Group score z_v is the SUM over active members of \mathrm{weights\_i}\cdot (\mathrm{logits\_iv}+\mathrm{bias\_iv}), divided by the NUMBER of active members, not \sum(\mathrm{weights}).
  • Thus tied all-active positions with unit weights average their logits/biases. Legal classes are the INTERSECTION of allowed sets over ALL members.
  • Every fixed (valid non-updated) member additionally forces its current identity, so consistent fixed ties force a one-hot outcome; contradictory fixed identities or forbidden fixed identities leave empty support. Groups with no active members also have empty support. Config top_k is 0 (default, no top-k) or an integer1..V.
  • Rank legal classes by descending score with smaller class ID breaking ties and retain k if enabled. Config top_p is in (0,1], default 1.
  • If \mathrm{top\_p}<1, softmax the FILTER scores on the top-k-retained support and apply nucleus_rule: 'standard' (default) keeps each class whose cumulative mass before it is < p, including the first crossing class; 'esm3' keeps classes whose cumulative mass THROUGH them is \le p and always keeps the highest-ranked legal class, thus normally excluding the first crossing class.
  • For p=1 neither rule filters. Empty support stays empty under both rules. Config filter_order is 'before_temperature' (default, filter z) or 'after_temperature' (filter z/T). top-k always precedes nucleus filtering.
  • For T=0, use z for filtering. After filtering, T>0 yields \operatorname{softmax}(z/T); T=0 yields a one-hot at the highest retained z, ties to smaller ID. These are all keys.
  • For T>0, sample the first class in ORIGINAL ascending vocabulary order whose cumulative final probability is STRICTLY greater than uniform. If roundoff leaves no crossing, choose the last positive-probability class.
  • Return sampled [B,G] (-1 for empty support), probabilities [B,G,V], group_valid [B,G], \mathrm{log\_probability}[B,G]=\operatorname{log}(probability of sampled class) or 0 if empty, and updated \mathrm{tokens}[B,L]/\mathrm{updated}[B,L].
  • Only active positions in valid groups change; invalid groups leave tokens unchanged, and all fixed/padding positions are preserved. Invalid-group probabilities are exactly zero. No in-place mutation. This is one categorical update from supplied logits, not a neural decoder or a source-specific random-number stream.

Why this matters

Tied positions share a decision, so their logits and allowed classes must be resolved at group level before a supplied random number selects a class.

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 constrained_categorical_sampling(
    logits: torch.Tensor,  # (B, L, V)
    temperature: torch.Tensor,  # (B, G)
    uniform: torch.Tensor,  # (B, G)
    tokens: torch.Tensor,  # (B, L)
    group_ids: torch.Tensor,  # (B, L)
    allowed: torch.Tensor,  # (B, L, V)
    parameters: dict,
    masks: dict,
    top_k: int = 0,
    top_p: float = 1.0,
    filter_order: str = 'before_temperature',
    nucleus_rule: str = 'standard',
) -> dict[str, torch.Tensor]:
    """Return dict[str, torch.Tensor]:
    
    tokens: (B, L).
    updated: (B, L).
    sampled: (B, G).
    group_valid: (B, G).
    probabilities: (B, G, V).
    log_probability: (B, G)."""
    # Implement the operation. Inputs and test setup are supplied by BioTorch.
    raise NotImplementedError("Implement constrained_categorical_sampling")

Ready to implement it?

3 progressive hints, a solution walkthrough, and grading that checks values, shapes and gradients are waiting in the workspace.

Write and run your solution Sign in

Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.

Sources and further reading

A primitive exercise, not an end-to-end reproduction of the named models. No affiliation or endorsement is implied.