invirtuolabs/InVirtuoGen_results

Public repository to reproduce results

Python

12

9 commits

updated Aug 3, 2026

See the code

README

InVirtuoGen: Uniform-Source Discrete Flows for Drug Discovery

Repository to reproduce results from the paper.

🚀 Quick Start

Setup Environment

On ARM-based environments

mamba create -n invgen python=3.10.16 -y
mamba activate invgen
pip install -r requirements.txt
pip install -e .

We also provide a Dockerfile for aarch64-based environments - the results from the paper were produced within the corresponding Docker container and should be reproducible - although we could not check it on another cluster.

Download Checkpoints

mkdir checkpoints && cd checkpoints
mkdir checkpoints && cd checkpoints
curl -L "https://zenodo.org/records/16874868/files/invirtuo_gen.ckpt.zip?download=1" -o invirtuo_gen.ckpt.zip
curl -L "https://zenodo.org/records/16874868/files/invirtuo_gen_big.ckpt.zip?download=1" -o invirtuo_gen_big.ckpt.zip
unzip invirtuo_gen.ckpt.zip && unzip invirtuo_gen_big.ckpt.zip
cd ..

Available Models:

  • invirtuo_gen.ckpt - Standard model for general use
  • invirtuo_gen_big.ckpt - Larger model for optimal performance

Quick Generation:

python -m in_virtuo_gen.generate \
    --ckpt_path checkpoints/invirtuo_gen.ckpt \
    --num_samples 1000 \
    --batch_size 200

Reproduce Results in Paper

1. De Novo Molecule Generation

Reproduce Quality-Diversity Analysis:

Quality vs Diversity (~6h on RTX 4090 for 3 seeds)

python -m in_virtuo_gen.evaluation.denovo \
    --checkpoint_path checkpoints/invirtuo_gen_big.ckpt \
    --dt 0.1 0.01 0.001 \
    --num_samples 1000 \
    --eta 999 \
    --num_seeds 3 \
    --device 0

2. Fragment-Constrained Generation

(<1h on RTX 4090 for 3 seeds)

Design molecules containing specific fragments while optimizing properties. Motif Extension Linker Design Scaffold Decoration Superstructure Generation

python -m in_virtuo_gen.evaluation.downstream \
--model_path checkpoints/invirtuo_gen_big.ckpt\
 --dt 0.01\
 --temperature 1\
 --noise 0\
 --eta 999\
 --device 0 --all

Supported Tasks:

  • Motif Extension - Growing fixed motifs with new substituents
  • Linker Design - Connecting fragments with feasible linkers
  • Scaffold Decoration - Adding functional groups at defined positions
  • Superstructure Generation - Assembling multiple fragments

3. Target Property Optimization

Optimize molecular properties using genetic algorithms + reinforcement learning.

Setup Vocab: (~12 hours on 16 CPU cores)

mkdir -p data
wget -O data/frags_zinc250.csv https://zenodo.org/records/16742898/files/frags_zinc250.csv
python -m in_virtuo_reinforce.preprocess.get_vocab \
    --datapath data/frags_zinc250.csv \
    --outpath in_virtuo_reinforce/vocab/zinc250k.csv

This step scores all ~250k ZINC molecules against all 23 oracles and writes in_virtuo_reinforce/vocab/zinc250k.csv (~106 MB), which the --use_prescreen path reads. The built file is not tracked in this repository, since it exceeds GitHub's 100 MB per-file limit; rebuild it with the command above. get_vocab.py checkpoints per property and supports --resume, so an interrupted build never re-scores a finished oracle.

With Prescreening ZINC250k:

State-of-the-art results on PMO benchmark

OracleInVirtuoGenGenMolf-RAG
albuterol similarity0.975 (±0.016)0.9370.977
amlodipine mpo0.836 (±0.031)0.8100.749
celecoxib rediscovery0.839 (±0.013)0.8260.778
deco hop0.968 (±0.012)0.9600.936
drd20.995 (±0.000)0.9950.992
fexofenadine mpo0.904 (±0.000)0.8940.856
gsk3b0.988 (±0.001)0.9860.969
isomers c7h8n2o20.988 (±0.002)0.9420.955
isomers c9h10n2o2pf2cl0.898 (±0.018)0.8330.850
jnk30.898 (±0.031)0.9060.904
median10.386 (±0.003)0.3980.340
median20.377 (±0.006)0.3590.323
mestranol similarity0.991 (±0.002)0.9820.671
osimertinib mpo0.881 (±0.012)0.8760.866
perindopril mpo0.753 (±0.019)0.7180.681
qed0.943 (±0.000)0.9420.939
ranolazine mpo0.854 (±0.012)0.8210.820
scaffold hop0.711 (±0.081)0.6280.576
sitagliptin mpo0.743 (±0.022)0.5840.601
thiothixene rediscovery0.652 (±0.024)0.6920.584
troglitazone rediscovery0.853 (±0.003)0.8670.448
valsartan smarts0.935 (±0.012)0.8220.627
zaleplon mpo0.624 (±0.040)0.5840.486
Sum18.993 (±0.219)18.36216.928

Results Table

python -m in_virtuo_reinforce.evaluation.results_table --results_root results/target_property/prescreen_3_runs --incl

Reproduce Results - Run Optimization (~36h on RTX 4090 for 3 seeds): Command:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --use_prompter --use_mut --train_mut --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100  --start_rank 1 --use_prescreen

Without Prescreening ZINC250k:

State-of-the-art results on PMO benchmark

OracleInVirtuoGen (no prescreen)Gen. GFNMol GAREINVENTGraph GA
albuterol similarity0.950 (±0.017)0.9490.8960.8820.838
amlodipine mpo0.733 (±0.043)0.7610.6880.6350.661
celecoxib rediscovery0.798 (±0.028)0.8020.5670.7130.630
deco hop0.748 (±0.109)0.7330.6490.6660.619
drd20.985 (±0.002)0.9740.9360.9450.964
fexofenadine mpo0.845 (±0.016)0.8560.8250.7840.760
gsk3b0.952 (±0.016)0.8810.8430.8650.788
isomers c7h8n2o20.968 (±0.005)0.9690.8780.8520.862
isomers c9h10n2o2pf2cl0.874 (±0.013)0.8970.8650.6420.719
jnk30.825 (±0.016)0.7640.7020.7830.553
median10.342 (±0.008)0.3790.2570.3560.294
median20.288 (±0.008)0.2940.3010.2760.273
mestranol similarity0.797 (±0.033)0.7080.5910.6180.579
osimertinib mpo0.870 (±0.005)0.8600.8440.8370.831
perindopril mpo0.645 (±0.032)0.5950.5470.5370.538
qed0.942 (±0.000)0.9420.9410.9410.940
ranolazine mpo0.848 (±0.010)0.8190.8040.7600.728
scaffold hop0.589 (±0.021)0.6150.5270.5600.517
sitagliptin mpo0.709 (±0.029)0.6340.5820.0210.433
thiothixene rediscovery0.625 (±0.014)0.5830.5190.5340.479
troglitazone rediscovery0.595 (±0.053)0.5110.4270.4410.390
valsartan smarts0.210 (±0.297)0.1350.0000.1780.000
zaleplon mpo0.536 (±0.006)0.5520.5190.3580.346
Sum16.676 (±0.256)16.21314.70814.18413.742

Results Table

python -m in_virtuo_reinforce.evaluation.results_table --results_root results/target_property/no_prescreen_3_runs --include_std --exclude_prescreen

Reproduce Results - Run Optimization (~36h on RTX 4090 for 3 seeds):

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 5 --clip_eps 0.2 --dt 0.01 --experience_replay 300 --vocab_size 10 --lr 0.1 --use_prompter --use_mut --train_mut --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_rank 1

3.b Ablations:

Results Table

python  -m in_virtuo_reinforce.evaluation.results_table --ablation_mode \
 --results_path   results/target_property/prescreen_with_exp  results/target_property/prescreen_eta999_start_t_0.2 results/target_property/prescreen_eta999 results/target_property/prescreen_no_bandit results/target_property/prescreen_no_mutation   results/target_property/prescreen_no_ppo results/target_property/no_prescreen_no_experience_replay results/target_property/no_prescreen_no_prompter_no_mut \
  --model_names  "With Experience Replay" "Sampling with eq.~\ref{eq:our_update}, $t_{start}=0.2$" "Sampling with eq.~\ref{eq:our_update}" "No Bandit" "No Mutation" "No PPO" "No Prescreen, No Experience Replay" "No Prompter, No Mutation, No Prescreen"

Commands: With Experience Replay

-m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 300 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_seed 1 --start_rank 1 --use_prescreen --use_prompter --use_mutation --train_mutation

Commands: No Bandit:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_rank 1 --use_prescreen --use_prompter --use_mutation --train_mutation --no_bandit

Commands: No Mutation:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 20 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --use_prompter --experience_replay 300 --lr 0.1 --vocab_size 10 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00005 --tot_offspring_size 100 --use_prescreen --num_seeds 1 --start_rank 1

Commands: no PPO:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 10 --num_timesteps 0 --num_reinforce_steps 0 --clip_eps 0.2 --dt 0.01 --use_prompter --experience_replay 300 --lr 0.1 --vocab_size 10 --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00005 --tot_offspring_size 100 --use_prescreen --num_seeds 1 --start_rank 1

Commands: No Experience Replay:

-m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 5 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_rank 1 --use_prompter --use_mutation --train_mutation

Commands: No Prompter, No Mutation:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 100 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 300 --lr 0.1 --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00005 --tot_offspring_size 100 --num_seeds 1 --start_rank 1

Commands: Our Sampling:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --use_prompter --use_mutation --train_mutation --use_prescreen --eta 999 --num_seeds 1

Commands: Our Sampling, different start t:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0.2 --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --identifier 898948 --start_seed 0 --start_rank 1 --use_prompter --use_mutation --train_mutation --eta 999 --use_prescreen --num_seeds 1
OracleWith Experience ReplayNo BanditNo MutationNo PPONo Prescreen, No Experience ReplayNo Prompter, No Mutation, No Prescreen
albuterol similarity0.9930.9910.9280.8810.9690.851
amlodipine mpo0.8130.7640.7770.7550.6790.547
celecoxib rediscovery0.8720.7850.7580.8150.8340.768
deco hop0.9600.9880.9700.9430.6510.659
drd20.9950.9950.9860.9860.9840.950
fexofenadine mpo0.9080.9130.8340.8530.8520.735
gsk3b0.9900.9920.9760.9720.9490.867
isomers c7h8n2o20.9890.9780.9670.9740.9710.857
isomers c9h10n2o2pf2cl0.8760.9190.8510.8340.8880.798
jnk30.8920.9170.8070.8890.8250.701
median10.3820.3850.3700.3630.3420.308
median20.3330.3770.3310.3630.3040.241
mestranol similarity0.9920.9830.9630.9620.7230.764
osimertinib mpo0.8780.8680.8570.8580.8640.802
perindopril mpo0.7330.7100.6950.6820.6270.463
qed0.9430.9440.9430.9430.9430.941
ranolazine mpo0.8780.8660.8070.8160.8400.762
scaffold hop0.6540.6570.7900.5950.6190.522
sitagliptin mpo0.7720.7380.4570.5460.6930.324
thiothixene rediscovery0.6850.6250.5880.5260.6200.465
troglitazone rediscovery0.8700.8550.8330.8360.4340.418
valsartan smarts0.8700.9270.7660.7150.0000.150
zaleplon mpo0.6170.6050.5760.6530.5200.458
Sum18.89318.78217.83117.75816.13114.349

3.c Comparison in the Unlimited-Oracle-Call Regime (Graph-GRPO)

Some methods, notably Graph-GRPO, report PMO scores without counting the oracle calls spent on training the generative model, and only count the calls of the final optimization run. We consider this at odds with the purpose of the benchmark, which is sample efficiency with respect to an expensive oracle, but report results under that convention for completeness (see the appendix of the paper).

Those experiments use a two-phase protocol (a finetuning phase of at most 100k oracle calls per task, followed by the standard 10k-call PMO run from the finetuned policy) that is not part of the code on main. The code, submission scripts, per-oracle result CSVs and table-building recipe for them live on the grpo branch:

git checkout grpo
cat EVAL_RUNS.md   # which run produced which table, and the exact commands

4. Lead Optimization:

(We were unable to install the required dependencies for these experiments in the Dockerfile on an aarch64 environment. On ARM systems, the setup works by simply running pip install -r requirements.txt). Also we can not guarantee exact reproducability here, due to the stochasticity of the docking with openVINA.

Protein (DS/QED/SA)GenMol (δ=0.4)RetMol (δ=0.4)GraphGA (δ=0.4)InVirtuoGen (δ=0.4)GenMol (δ=0.6)RetMol (δ=0.6)GraphGA (δ=0.6)InVirtuoGen (δ=0.6)
parp1
-7.3/0.888/2.61-10.6-9.0-8.3-14.1 (±0.4)-10.4–-8.6-12.3 (±0.2)
-7.8/0.758/2.74-11.0-10.7-8.9-13.4 (±0.6)-9.7–-8.1-11.7 (±0.5)
-8.2/0.438/2.91-11.3-10.9–-9.0 (±1.3)-9.2––-10.7 (±0.9)
fa7
-6.4/0.284/2.29-8.4-8.0-7.8-8.4 (±0.4)-7.3-7.6-7.6-7.7 (±0.4)
-6.7/0.186/3.39-8.4–-8.2-8.9 (±0.5)-7.6–-7.6-7.5 (±0.3)
-8.5/0.156/2.66–––(-8.0) (±0.3)–––(-7.4) (±0.4)
5ht1b
-4.5/0.438/3.93-12.9-12.1-11.7-13.3 (±0.1)-12.1–-11.3-12.4 (±0.5)
-7.6/0.767/3.29-12.3-9.0-12.1-12.0 (±0.7)-12.0-10.0-12.0-12.0 (±0.4)
-9.8/0.716/4.69-11.6––-10.9 (±0.2)-10.5––-10.6 (±0.1)
braf
-9.3/0.235/2.69-10.8-11.6-9.8-10.1 (±0.0)–––-9.7 (±0.1)
-9.4/0.346/2.49-10.8––-10.8 (±0.1)-9.7––-10.4 (±0.3)
-9.8/0.255/2.38-10.6–-11.6-10.6 (±0.4)-10.5–-10.4-10.3 (±0.3)
jak2
-7.7/0.725/2.89-10.2-8.2-8.7-10.2 (±0.8)-9.3-8.1–-9.7 (±0.3)
-8.0/0.712/3.09-10.0-9.0-9.2-10.5 (±0.3)-9.4–-9.2-10.4 (±0.1)
-8.6/0.482/3.10-9.8––-10.2 (±0.2)–––-10.3 (±0.2)
Sum-148.7-88.5-96.3-152.4 (-160.4)-117.7-25.7-74.8-145.7 (-153.1)

Commands

python -m in_virtuo_reinforce.ppo_docking --device 1 --start_t 0. --offspring_size 50 --seed 0 --max_oracle_calls 1000 --num_reinforce_steps 50 --clip_eps 0.5 --start_task 0 --experience_replay_size 100 --dt 0.01 --c_neg 1 --dt 0.01 --tot_offspring 100 --vocab_size 10 --num_timesteps 50 --start_task 0

reproduce table

 python -m in_virtuo_reinforce.evaluation.results_table_lead --sim_results_dir results/lead_optimization/sim_constraint

4.b Without Similarity Constraints:

 python -m in_virtuo_reinforce.ppo_docking --device 1 --start_t 0. --offspring_size 50 --seed 0 --max_oracle_calls 1000 --num_reinforce_steps 50 --clip_eps 0.5 --start_task 0 --experience_replay_size 100 --dt 0.01 --c_neg 1 --dt 0.01 --tot_offspring 100 --vocab_size 10 --num_timesteps 50 --no_sim_constraint

reproduce table

 python -m in_virtuo_reinforce.evaluation.results_table_lead --mode nosim --no_sim results/lead_optimization/no_sim_constraint

Hugging Face:

Paper + Model also available at: https://huggingface.co/papers/2509.26405

📄 Citation

If you use this work, please cite:

@misc{kaech2025refinedrugsdontcomplete,
      title={Refine Drugs, Don't Complete Them: Uniform-Source Discrete Flows for Fragment-Based Drug Discovery},
      author={Benno Kaech and Luis Wyss and Karsten Borgwardt and Gianvito Grasso},
      year={2025},
      eprint={2509.26405},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2509.26405 },
}

📧 Contact

📬 [email protected]

⚖️ License and Terms of Use

The InVirtuoGEN source code is licensed under the Creative Commons Attribution-Non-Commercial ShareAlike International License, Version 4.0 (CC-BY-NC-SA 4.0) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://creativecommons.org/licenses/by-nc-sa/4.0/

The InVirtuoGEN model parameters are made available under the InVirtuoGEN Model Parameters Terms of Use (the "Terms"); you may not use these except in compliance with the Terms. You may obtain a copy of the Terms at WEIGHTS_TERMS_OF_USE.md.

Unless required by applicable law, InVirtuoGEN and its output are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. You are solely responsible for determining the appropriateness of using InVirtuoGEN, or using or distributing its source code or output, and assume any and all risks associated with such use or distribution and your exercise of rights and obligations under the relevant terms. Output are predictions with varying levels of confidence and should be interpreted carefully. Use discretion before relying on, publishing, downloading or otherwise using the InVirtuoGEN Assets.

invirtuolabs/InVirtuoGen_results

Public repository to reproduce results

Python

12

9 commits

updated Aug 3, 2026

See the code

README

InVirtuoGen: Uniform-Source Discrete Flows for Drug Discovery

Repository to reproduce results from the paper.

🚀 Quick Start

Setup Environment

On ARM-based environments

mamba create -n invgen python=3.10.16 -y
mamba activate invgen
pip install -r requirements.txt
pip install -e .

We also provide a Dockerfile for aarch64-based environments - the results from the paper were produced within the corresponding Docker container and should be reproducible - although we could not check it on another cluster.

Download Checkpoints

mkdir checkpoints && cd checkpoints
mkdir checkpoints && cd checkpoints
curl -L "https://zenodo.org/records/16874868/files/invirtuo_gen.ckpt.zip?download=1" -o invirtuo_gen.ckpt.zip
curl -L "https://zenodo.org/records/16874868/files/invirtuo_gen_big.ckpt.zip?download=1" -o invirtuo_gen_big.ckpt.zip
unzip invirtuo_gen.ckpt.zip && unzip invirtuo_gen_big.ckpt.zip
cd ..

Available Models:

  • invirtuo_gen.ckpt - Standard model for general use
  • invirtuo_gen_big.ckpt - Larger model for optimal performance

Quick Generation:

python -m in_virtuo_gen.generate \
    --ckpt_path checkpoints/invirtuo_gen.ckpt \
    --num_samples 1000 \
    --batch_size 200

Reproduce Results in Paper

1. De Novo Molecule Generation

Reproduce Quality-Diversity Analysis:

Quality vs Diversity (~6h on RTX 4090 for 3 seeds)

python -m in_virtuo_gen.evaluation.denovo \
    --checkpoint_path checkpoints/invirtuo_gen_big.ckpt \
    --dt 0.1 0.01 0.001 \
    --num_samples 1000 \
    --eta 999 \
    --num_seeds 3 \
    --device 0

2. Fragment-Constrained Generation

(<1h on RTX 4090 for 3 seeds)

Design molecules containing specific fragments while optimizing properties. Motif Extension Linker Design Scaffold Decoration Superstructure Generation

python -m in_virtuo_gen.evaluation.downstream \
--model_path checkpoints/invirtuo_gen_big.ckpt\
 --dt 0.01\
 --temperature 1\
 --noise 0\
 --eta 999\
 --device 0 --all

Supported Tasks:

  • Motif Extension - Growing fixed motifs with new substituents
  • Linker Design - Connecting fragments with feasible linkers
  • Scaffold Decoration - Adding functional groups at defined positions
  • Superstructure Generation - Assembling multiple fragments

3. Target Property Optimization

Optimize molecular properties using genetic algorithms + reinforcement learning.

Setup Vocab: (~12 hours on 16 CPU cores)

mkdir -p data
wget -O data/frags_zinc250.csv https://zenodo.org/records/16742898/files/frags_zinc250.csv
python -m in_virtuo_reinforce.preprocess.get_vocab \
    --datapath data/frags_zinc250.csv \
    --outpath in_virtuo_reinforce/vocab/zinc250k.csv

This step scores all ~250k ZINC molecules against all 23 oracles and writes in_virtuo_reinforce/vocab/zinc250k.csv (~106 MB), which the --use_prescreen path reads. The built file is not tracked in this repository, since it exceeds GitHub's 100 MB per-file limit; rebuild it with the command above. get_vocab.py checkpoints per property and supports --resume, so an interrupted build never re-scores a finished oracle.

With Prescreening ZINC250k:

State-of-the-art results on PMO benchmark

OracleInVirtuoGenGenMolf-RAG
albuterol similarity0.975 (±0.016)0.9370.977
amlodipine mpo0.836 (±0.031)0.8100.749
celecoxib rediscovery0.839 (±0.013)0.8260.778
deco hop0.968 (±0.012)0.9600.936
drd20.995 (±0.000)0.9950.992
fexofenadine mpo0.904 (±0.000)0.8940.856
gsk3b0.988 (±0.001)0.9860.969
isomers c7h8n2o20.988 (±0.002)0.9420.955
isomers c9h10n2o2pf2cl0.898 (±0.018)0.8330.850
jnk30.898 (±0.031)0.9060.904
median10.386 (±0.003)0.3980.340
median20.377 (±0.006)0.3590.323
mestranol similarity0.991 (±0.002)0.9820.671
osimertinib mpo0.881 (±0.012)0.8760.866
perindopril mpo0.753 (±0.019)0.7180.681
qed0.943 (±0.000)0.9420.939
ranolazine mpo0.854 (±0.012)0.8210.820
scaffold hop0.711 (±0.081)0.6280.576
sitagliptin mpo0.743 (±0.022)0.5840.601
thiothixene rediscovery0.652 (±0.024)0.6920.584
troglitazone rediscovery0.853 (±0.003)0.8670.448
valsartan smarts0.935 (±0.012)0.8220.627
zaleplon mpo0.624 (±0.040)0.5840.486
Sum18.993 (±0.219)18.36216.928

Results Table

python -m in_virtuo_reinforce.evaluation.results_table --results_root results/target_property/prescreen_3_runs --incl

Reproduce Results - Run Optimization (~36h on RTX 4090 for 3 seeds): Command:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --use_prompter --use_mut --train_mut --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100  --start_rank 1 --use_prescreen

Without Prescreening ZINC250k:

State-of-the-art results on PMO benchmark

OracleInVirtuoGen (no prescreen)Gen. GFNMol GAREINVENTGraph GA
albuterol similarity0.950 (±0.017)0.9490.8960.8820.838
amlodipine mpo0.733 (±0.043)0.7610.6880.6350.661
celecoxib rediscovery0.798 (±0.028)0.8020.5670.7130.630
deco hop0.748 (±0.109)0.7330.6490.6660.619
drd20.985 (±0.002)0.9740.9360.9450.964
fexofenadine mpo0.845 (±0.016)0.8560.8250.7840.760
gsk3b0.952 (±0.016)0.8810.8430.8650.788
isomers c7h8n2o20.968 (±0.005)0.9690.8780.8520.862
isomers c9h10n2o2pf2cl0.874 (±0.013)0.8970.8650.6420.719
jnk30.825 (±0.016)0.7640.7020.7830.553
median10.342 (±0.008)0.3790.2570.3560.294
median20.288 (±0.008)0.2940.3010.2760.273
mestranol similarity0.797 (±0.033)0.7080.5910.6180.579
osimertinib mpo0.870 (±0.005)0.8600.8440.8370.831
perindopril mpo0.645 (±0.032)0.5950.5470.5370.538
qed0.942 (±0.000)0.9420.9410.9410.940
ranolazine mpo0.848 (±0.010)0.8190.8040.7600.728
scaffold hop0.589 (±0.021)0.6150.5270.5600.517
sitagliptin mpo0.709 (±0.029)0.6340.5820.0210.433
thiothixene rediscovery0.625 (±0.014)0.5830.5190.5340.479
troglitazone rediscovery0.595 (±0.053)0.5110.4270.4410.390
valsartan smarts0.210 (±0.297)0.1350.0000.1780.000
zaleplon mpo0.536 (±0.006)0.5520.5190.3580.346
Sum16.676 (±0.256)16.21314.70814.18413.742

Results Table

python -m in_virtuo_reinforce.evaluation.results_table --results_root results/target_property/no_prescreen_3_runs --include_std --exclude_prescreen

Reproduce Results - Run Optimization (~36h on RTX 4090 for 3 seeds):

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 5 --clip_eps 0.2 --dt 0.01 --experience_replay 300 --vocab_size 10 --lr 0.1 --use_prompter --use_mut --train_mut --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_rank 1

3.b Ablations:

Results Table

python  -m in_virtuo_reinforce.evaluation.results_table --ablation_mode \
 --results_path   results/target_property/prescreen_with_exp  results/target_property/prescreen_eta999_start_t_0.2 results/target_property/prescreen_eta999 results/target_property/prescreen_no_bandit results/target_property/prescreen_no_mutation   results/target_property/prescreen_no_ppo results/target_property/no_prescreen_no_experience_replay results/target_property/no_prescreen_no_prompter_no_mut \
  --model_names  "With Experience Replay" "Sampling with eq.~\ref{eq:our_update}, $t_{start}=0.2$" "Sampling with eq.~\ref{eq:our_update}" "No Bandit" "No Mutation" "No PPO" "No Prescreen, No Experience Replay" "No Prompter, No Mutation, No Prescreen"

Commands: With Experience Replay

-m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 300 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_seed 1 --start_rank 1 --use_prescreen --use_prompter --use_mutation --train_mutation

Commands: No Bandit:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_rank 1 --use_prescreen --use_prompter --use_mutation --train_mutation --no_bandit

Commands: No Mutation:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 20 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --use_prompter --experience_replay 300 --lr 0.1 --vocab_size 10 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00005 --tot_offspring_size 100 --use_prescreen --num_seeds 1 --start_rank 1

Commands: no PPO:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 10 --num_timesteps 0 --num_reinforce_steps 0 --clip_eps 0.2 --dt 0.01 --use_prompter --experience_replay 300 --lr 0.1 --vocab_size 10 --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00005 --tot_offspring_size 100 --use_prescreen --num_seeds 1 --start_rank 1

Commands: No Experience Replay:

-m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 5 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --start_rank 1 --use_prompter --use_mutation --train_mutation

Commands: No Prompter, No Mutation:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 100 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 300 --lr 0.1 --first_pop_size 100 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00005 --tot_offspring_size 100 --num_seeds 1 --start_rank 1

Commands: Our Sampling:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0. --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --use_prompter --use_mutation --train_mutation --use_prescreen --eta 999 --num_seeds 1

Commands: Our Sampling, different start t:

python -m in_virtuo_reinforce.genetic_ppo --ckpt checkpoints/invirtuo_gen.ckpt --device 0 --start_t 0.2 --offspring_size 50 --num_timesteps 50 --num_reinforce_steps 10 --clip_eps 0.2 --dt 0.01 --experience_replay 0 --vocab_size 10 --lr 0.1 --first_pop_size 10 --aggressive_bandit --max_oracle_calls 10000 --c_neg 1 --mutation_size 20 --rl_lr 0.00001 --tot_offspring_size 100 --identifier 898948 --start_seed 0 --start_rank 1 --use_prompter --use_mutation --train_mutation --eta 999 --use_prescreen --num_seeds 1
OracleWith Experience ReplayNo BanditNo MutationNo PPONo Prescreen, No Experience ReplayNo Prompter, No Mutation, No Prescreen
albuterol similarity0.9930.9910.9280.8810.9690.851
amlodipine mpo0.8130.7640.7770.7550.6790.547
celecoxib rediscovery0.8720.7850.7580.8150.8340.768
deco hop0.9600.9880.9700.9430.6510.659
drd20.9950.9950.9860.9860.9840.950
fexofenadine mpo0.9080.9130.8340.8530.8520.735
gsk3b0.9900.9920.9760.9720.9490.867
isomers c7h8n2o20.9890.9780.9670.9740.9710.857
isomers c9h10n2o2pf2cl0.8760.9190.8510.8340.8880.798
jnk30.8920.9170.8070.8890.8250.701
median10.3820.3850.3700.3630.3420.308
median20.3330.3770.3310.3630.3040.241
mestranol similarity0.9920.9830.9630.9620.7230.764
osimertinib mpo0.8780.8680.8570.8580.8640.802
perindopril mpo0.7330.7100.6950.6820.6270.463
qed0.9430.9440.9430.9430.9430.941
ranolazine mpo0.8780.8660.8070.8160.8400.762
scaffold hop0.6540.6570.7900.5950.6190.522
sitagliptin mpo0.7720.7380.4570.5460.6930.324
thiothixene rediscovery0.6850.6250.5880.5260.6200.465
troglitazone rediscovery0.8700.8550.8330.8360.4340.418
valsartan smarts0.8700.9270.7660.7150.0000.150
zaleplon mpo0.6170.6050.5760.6530.5200.458
Sum18.89318.78217.83117.75816.13114.349

3.c Comparison in the Unlimited-Oracle-Call Regime (Graph-GRPO)

Some methods, notably Graph-GRPO, report PMO scores without counting the oracle calls spent on training the generative model, and only count the calls of the final optimization run. We consider this at odds with the purpose of the benchmark, which is sample efficiency with respect to an expensive oracle, but report results under that convention for completeness (see the appendix of the paper).

Those experiments use a two-phase protocol (a finetuning phase of at most 100k oracle calls per task, followed by the standard 10k-call PMO run from the finetuned policy) that is not part of the code on main. The code, submission scripts, per-oracle result CSVs and table-building recipe for them live on the grpo branch:

git checkout grpo
cat EVAL_RUNS.md   # which run produced which table, and the exact commands

4. Lead Optimization:

(We were unable to install the required dependencies for these experiments in the Dockerfile on an aarch64 environment. On ARM systems, the setup works by simply running pip install -r requirements.txt). Also we can not guarantee exact reproducability here, due to the stochasticity of the docking with openVINA.

Protein (DS/QED/SA)GenMol (δ=0.4)RetMol (δ=0.4)GraphGA (δ=0.4)InVirtuoGen (δ=0.4)GenMol (δ=0.6)RetMol (δ=0.6)GraphGA (δ=0.6)InVirtuoGen (δ=0.6)
parp1
-7.3/0.888/2.61-10.6-9.0-8.3-14.1 (±0.4)-10.4–-8.6-12.3 (±0.2)
-7.8/0.758/2.74-11.0-10.7-8.9-13.4 (±0.6)-9.7–-8.1-11.7 (±0.5)
-8.2/0.438/2.91-11.3-10.9–-9.0 (±1.3)-9.2––-10.7 (±0.9)
fa7
-6.4/0.284/2.29-8.4-8.0-7.8-8.4 (±0.4)-7.3-7.6-7.6-7.7 (±0.4)
-6.7/0.186/3.39-8.4–-8.2-8.9 (±0.5)-7.6–-7.6-7.5 (±0.3)
-8.5/0.156/2.66–––(-8.0) (±0.3)–––(-7.4) (±0.4)
5ht1b
-4.5/0.438/3.93-12.9-12.1-11.7-13.3 (±0.1)-12.1–-11.3-12.4 (±0.5)
-7.6/0.767/3.29-12.3-9.0-12.1-12.0 (±0.7)-12.0-10.0-12.0-12.0 (±0.4)
-9.8/0.716/4.69-11.6––-10.9 (±0.2)-10.5––-10.6 (±0.1)
braf
-9.3/0.235/2.69-10.8-11.6-9.8-10.1 (±0.0)–––-9.7 (±0.1)
-9.4/0.346/2.49-10.8––-10.8 (±0.1)-9.7––-10.4 (±0.3)
-9.8/0.255/2.38-10.6–-11.6-10.6 (±0.4)-10.5–-10.4-10.3 (±0.3)
jak2
-7.7/0.725/2.89-10.2-8.2-8.7-10.2 (±0.8)-9.3-8.1–-9.7 (±0.3)
-8.0/0.712/3.09-10.0-9.0-9.2-10.5 (±0.3)-9.4–-9.2-10.4 (±0.1)
-8.6/0.482/3.10-9.8––-10.2 (±0.2)–––-10.3 (±0.2)
Sum-148.7-88.5-96.3-152.4 (-160.4)-117.7-25.7-74.8-145.7 (-153.1)

Commands

python -m in_virtuo_reinforce.ppo_docking --device 1 --start_t 0. --offspring_size 50 --seed 0 --max_oracle_calls 1000 --num_reinforce_steps 50 --clip_eps 0.5 --start_task 0 --experience_replay_size 100 --dt 0.01 --c_neg 1 --dt 0.01 --tot_offspring 100 --vocab_size 10 --num_timesteps 50 --start_task 0

reproduce table

 python -m in_virtuo_reinforce.evaluation.results_table_lead --sim_results_dir results/lead_optimization/sim_constraint

4.b Without Similarity Constraints:

 python -m in_virtuo_reinforce.ppo_docking --device 1 --start_t 0. --offspring_size 50 --seed 0 --max_oracle_calls 1000 --num_reinforce_steps 50 --clip_eps 0.5 --start_task 0 --experience_replay_size 100 --dt 0.01 --c_neg 1 --dt 0.01 --tot_offspring 100 --vocab_size 10 --num_timesteps 50 --no_sim_constraint

reproduce table

 python -m in_virtuo_reinforce.evaluation.results_table_lead --mode nosim --no_sim results/lead_optimization/no_sim_constraint

Hugging Face:

Paper + Model also available at: https://huggingface.co/papers/2509.26405

📄 Citation

If you use this work, please cite:

@misc{kaech2025refinedrugsdontcomplete,
      title={Refine Drugs, Don't Complete Them: Uniform-Source Discrete Flows for Fragment-Based Drug Discovery},
      author={Benno Kaech and Luis Wyss and Karsten Borgwardt and Gianvito Grasso},
      year={2025},
      eprint={2509.26405},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2509.26405 },
}

📧 Contact

📬 [email protected]

⚖️ License and Terms of Use

The InVirtuoGEN source code is licensed under the Creative Commons Attribution-Non-Commercial ShareAlike International License, Version 4.0 (CC-BY-NC-SA 4.0) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://creativecommons.org/licenses/by-nc-sa/4.0/

The InVirtuoGEN model parameters are made available under the InVirtuoGEN Model Parameters Terms of Use (the "Terms"); you may not use these except in compliance with the Terms. You may obtain a copy of the Terms at WEIGHTS_TERMS_OF_USE.md.

Unless required by applicable law, InVirtuoGEN and its output are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. You are solely responsible for determining the appropriateness of using InVirtuoGEN, or using or distributing its source code or output, and assume any and all risks associated with such use or distribution and your exercise of rights and obligations under the relevant terms. Output are predictions with varying levels of confidence and should be interpreted carefully. Use discretion before relying on, publishing, downloading or otherwise using the InVirtuoGEN Assets.

Significant stargazers

Feiyang Cai

18 followers · starred Sep 2026