6. 3D structures (XYZ/AaronTools)¶
XYZGenAlgSolver swaps 3D fragments (substituents, ligands) in and out of a scaffold using AaronTools.py, rather than operating on a string representation. It shares the same AlphabetGenAlgSolver base as SmilesGenAlgSolver/SelfiesGenAlgSolver (Tutorial 2), with the same alphabet_list/starting_population/excluded_genes/equivalences shape, but with an assembler and fitness function that operate on AaronTools Geometry objects instead of strings.
Note
This page couldn’t be run against a live install while writing it: AaronTools isn’t installed in this environment. The snippet below is adapted directly from navicatGA/test/test_scaffolds.py (a real, working example in the test suite), not fabricated, but treat it as a starting point to verify yourself rather than a guaranteed-to-run copy-paste.
Install¶
pip install AaronTools # or: git clone https://github.com/QChASM/AaronTools.py
A scaffold-substitution example¶
import os
from navicatGA.xyz_solver import XYZGenAlgSolver
from navicatGA.chemistry_xyz import get_alphabet_from_path, get_default_alphabet
from navicatGA.wrappers_xyz import chromosome_to_xyz, geom2dihedral, geom2sub_sterimol
from navicatGA.quantum_wrappers_xyz import geom2ehomo # needs pyscf
# alphabet_list[0]: scaffold geometries loaded from a directory of .xyz files
# alphabet_list[1:]: substituents drawn from navicatGA's built-in default alphabet
alphabet_list = [
get_alphabet_from_path("path/to/scaffolds/"),
get_default_alphabet(),
get_default_alphabet(),
]
def fitness(geom):
ehomo = geom2ehomo(geom, lot=0)
dihedral = geom2dihedral(geom, "2", "1", "18", "21")
b1 = (geom2sub_sterimol(geom, "19", "B1") + geom2sub_sterimol(geom, "20", "B1")) / 2
return -(0.4 * dihedral + 0.31 * ehomo + 11.77 / b1 + 26.59)
solver = XYZGenAlgSolver(
n_genes=3,
pop_size=10,
max_gen=5,
mutation_rate=0.15,
fitness_function=fitness,
chromosome_to_xyz=chromosome_to_xyz(),
alphabet_list=alphabet_list,
starting_random=True,
random_state=24,
to_file=False,
)
result = solver.solve()
Differences from the string-based solvers¶
No reversal on crossover. SMILES/SELFIES crossover reverses gene order in some cases (see
create_offspringin each solver);XYZGenAlgSolvernever does, since reversing a 3D fragment order doesn’t have a meaningful analogue._setup_alphabet(..., sort_alphabet=False). AaronTools geometries aren’t orderable, unlike SMILES/SELFIES tokens, so the shared alphabet-setup logic skips sorting for this solver.chemistry_xyz.get_alphabet_from_path(directory)builds an alphabet from every structure file in a directory: the common way to seedalphabet_listhere, analogous to reading a runtime-computed alphabet forSmilesGenAlgSolver(see Tutorial 7 for that pattern in general).quantum_wrappers_xyz.py: optionalpyscf-based fitness helpers (electronic structure), same lazy-import treatment as the SELFIES/SMILES quantum wrappers (Tutorial 3).Heavier per-evaluation cost.
XYZGenAlgSolver’s own defaults reflect this:pop_size=5,max_gen=15(vs. 100/500 for the other solvers), since geometry optimization/fitness evaluation is typically far more expensive than a string-based one.
See navicatGA/queue_wrappers_xyz.py for a queue-based variant if your fitness evaluations should be dispatched to an external job scheduler instead of run in-process.