---
title: Scoring Functions
description: Weight REINVENT scoring components — qed, tanimoto, physchem, custom_alerts SMARTS — to sum to 1.0, add a custom Python scorer, and apply transforms.
---

Scoring is what defines the target profile [REINVENT](/docs/reinvent) optimizes toward: this page shows how to combine built-in components, weight them for multi-objective design, write custom scorers, and apply transforms. How you weight and transform the components most affects which molecules the run rewards.

## Scoring Functions in REINVENT 4

REINVENT 4, developed by AstraZeneca and available under Apache 2.0 license, uses scoring functions to guide reinforcement learning optimization. Scores provide feedback that shapes the generative model (RNN or transformer) to produce molecules with desired properties.

Multi-objective optimization is achieved by combining multiple scoring components, enabling simultaneous optimization for activity, ADMET properties, and synthetic accessibility.

For the complete list of available scoring components, see the [REINVENT 4 GitHub repository](https://github.com/MolecularAI/REINVENT4).

## Built-in components

- QED: `name: qed`
- Similarity to reference: `name: tanimoto` with `smiles` and `fp_type`
- Physchem filters: `name: physchem` with `ro5`, `hba`, `hbd`, `logp`, `tpsa`
- Custom Python: `name: custom_alerts` for SMARTS blocklists

## Example scoring config

```yaml
reinforcement_learning:
  scoring_function:
    name: custom
    parallel: true
    parameters:
      - name: qed
        weight: 0.2
      - name: tanimoto
        weight: 0.4
        parameters:
          smiles: "CC(=O)Oc1ccccc1C(=O)O"
          fp_type: morgan
          radius: 2
          nbits: 2048
      - name: physchem
        weight: 0.2
        parameters:
          ro5: true
          logp:
            min: -1.0
            max: 4.5
      - name: custom_alerts
        weight: 0.2
        parameters:
          smarts: ["[N+](=O)[O-]", "[#16]"]
```

Weights should sum to 1.0 to keep scores interpretable.

## Writing a custom component

```python
from reinvent_scoring import CustomSumScorer, ComponentParameters

def penalize_size(smiles: str) -> float:
    from rdkit import Chem
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        return 0.0
    return max(0.0, 1.0 - (mol.GetNumAtoms() / 80))

component = ComponentParameters(
    component_type="custom",
    name="size_penalty",
    weight=0.2,
    specific_parameters={"callable": penalize_size},
)

scorer = CustomSumScorer(parameters=[component])
```

Bundle custom components with your job so the module import path resolves inside
the worker.

## Tips

- Cache reference fingerprints to avoid recomputing each step.
- Guard against invalid SMILES and return 0.0 rather than raising inside custom
  scorers.
- Log per-component contributions during dry runs to calibrate weights before
  long campaigns.

## Scoring strategies for different design modes

REINVENT 4 supports multiple generative modes, each benefiting from tailored scoring approaches:

### De novo design
- Combine property predictors (QED, physchem) with activity models
- Use similarity constraints to stay within drug-like chemical space
- Include synthetic accessibility scores early in optimization

### Scaffold hopping
- Weight Tanimoto similarity to reference compounds
- Add scaffold diversity penalties to encourage novel cores
- Include activity prediction models for target engagement

### R-group replacement
- Focus scoring on the variable positions
- Use matched molecular pair analysis for SAR optimization
- Penalize groups with known liabilities (via SMARTS blocklists)

### Linker design
- Score linker length and flexibility
- Include strain energy or 3D geometry constraints
- Optimize for synthetic accessibility of the final molecule

## Transform functions

REINVENT 4 supports score transforms to shape the optimization landscape:

- **Sigmoid**: Soft thresholds for gradual property transitions
- **Step**: Hard cutoffs for binary constraints
- **Double sigmoid**: Define optimal ranges with upper and lower bounds
- **Reverse sigmoid**: Penalize values above a threshold

Apply transforms to convert raw predictions into normalized scores (0-1 range) suitable for RL optimization.
