Isolating black box objective functions#

Each black-box objective function in poli lives inside a conda environment. For example:

  • the foldx stability objective lives inside poli__protein, which has biopython, pdb-tools and other libraries that are required to interface well with proteins and their representations.

  • the dockstring objective lives inside poli__dockstring, which includes babel as part of its installation.

poli provides a way of running these objective functions in isolation.

Running objective functions in isolation#

Let’s say that your current environment doesn’t have the package dockstring installed. You can still run the objective function:

# No output: we don't have it installed.
!pip freeze | grep dockstring
from poli.objective_repository import DockstringBlackBox

f = DockstringBlackBox(target_name="DRD2")
poli 🧪: Starting the function dockstring as an isolated process.

As you can see, poli warns us that it is creating the conda environment associated with the black box function, and it is creating an isolated process where the objective can be run.

We can still evaluate f like normal:

import numpy as np

# The example from dockstring's documentation: risperidone.
x0 = np.array(["CC1=C(C(=O)N2CCCCC2=N1)CCN3CCC(CC3)C4=NOC5=C4C=CC(=C5)F"])

f(x0)
/Users/sjt972/anaconda3/envs/poli__dockstring/lib/python3.9/site-packages/dockstring/utils.py:77: DockstringWarning: Although Mac use is supported, docking scores on Mac do not always perfectly match scores from Linux. Therefore, extra care should be taken when comparing results to other platforms. In particular, the baselines in the DOCKSTRING paper were computed on Linux, so please do not directly compare your docking scores to the scores reported on the paper.
  warnings.warn(
array([[11.9]])

(Optional) What is happening under the hood?#

Each black box/problem implements all its complicated logic inside an AbstractIsolatedFunction, which lives in a different submodule inside the problem’s folder.

When we create a black box instance (like f = DockstringBlackBox(target_name="DRD2") here), one of two things happen:

  1. If we are able to import this isolated function, we do it directly and store it in f.inner_function,

  2. If we are not able to import it (say, because we don’t have the right dependencies in our current environment), poli starts an isolated process running with a pre-defined conda environment, and still stores it in f.inner_function. Calls to this isolated process are handled using multiprocess.

Read more#

You can check the individual dependencies of each black box inside their implementation, or in their documentation.