EGAD Library Manual

Energy Function

Preparing for Minimization

Reference State

One thing to consider before jumping into a minimization algorithm is the reference state for your design. This is often glossed-over because everyone has a different idea of how it should work and nobody has a good explanation for why they're right.

The reference state is the state you are designing away from. For some designs, this will be the unfolded state. Though some might tell you otherwise, we don't understand the unfolded state. We believe it to be disordered, but there is evidence for residual structure.

The objective of a protein design calculation is to maximize the energy difference between the reference state and the desired state. One reference state model that the original EGAD had success with was called the "random-sequence-structure" model. In a nutshell, this modeled the unfolded state by taking random chunks of protein out of the PDB and threading random sequences over them. The energy of the center residue was calculated and averaged over thousands of fragments to obtain a reference energy for each amino acid.

This simple, composition based reference energy is easy to construct and works well for stability predictions. The energy values can be found in the Resparam File:

Example 3.11: Creating a reference state

// Continue from example 3.10

// Construct the reference energy term
ReferenceEnergy energyR(&myProtein);

// Read reference energies from resparam file. This object was constructed
// in example 2.2
energyR.LoadFromResparam(resparam);

Piecing Together a Function

Now that we understand how to set up the individual pieces of our energy function, we have to prepare it for use by the minimization algorithm. The most obvious question to answer here is: how do we glue the pieces together into one function?

The answer is simple. There exists an EnergyFunction container object that can string an arbitrary number of energy terms together and act like one large energy term. Weights can be assigned to each term as well to form a linear combination of terms. Usually these weights are left to their default values of unity, but it may be interesting or useful to adjust these depending on the situation.

Example 3.12: Making a linear combination of energy terms

// Continue from example 3.11

// Create the Energy Function container object
PairwiseEnergyFunction energyFunction;

// Add each of the energy terms into the function
energyFunciton.AddTerm(&energyLJ);
energyFunciton.AddTerm(&energyC);
energyFunciton.AddTerm(&energyT);
energyFunciton.AddTerm(&energyS);
energyFunciton.AddTerm(&energyB);

// Add the reference energy term with a weight of -1.0
// (because we want to design AWAY from this state)
energyFunction.AddTerm(&energyR, -1.0);

This energy function can now be passed to a minimizer just like any other energy term. Each time an energy is requested from it, it will calculate the energy of each of its components, multiply them by their associated weights, and return the sum.

Precalculating an Energy Table

Another important issue is the need for precalculation. Minimizers will often ask for the same energy values multiple times. It would be wasteful to re-calculate the energy each time it was requested, so we would prefer to store already-calculated values for fast lookup by the minimizer. We will refer to these sets of precalculated values as energy tables.

There are objects available to store energy tables in memory for fast lookup. They attempt to be smart about compressing large blocks of zero-valued energies to take up the smallest footprint possible without sacrificing performance on energy lookup.

Example 3.13: Precalculating an energy table

// Continue from example 3.12

// Create the energy table object. The 'sparse' in the object name
// refers to the fact that this table attempts to save memory by
// collapsing empty (zeroed) areas of the table.
SparseEnergyTable energyTable;

// Copy the values from an energy term into this table. This function
// requests all possible energy values from the passed term and stores
// their values in the table.
energyTable.Copy(&energyFunction);

Saving and Loading Energy Tables

One advantage to precalculating energy tables is that they can be saved to and loaded from disk. This allows multiple minimization runs on the same energy table without paying the cost of calculation each time. It also allows tools to view and manipulate data within the energy tables, which can be useful for analysis of design results.

Because energy tables can be very large, EGAD Library uses the zlib compression library to store energy tables in compressed format. This prohibits the use of C++ standard I/O, as is preferred in most read/write functions in the library. Instead, we provide a filename:

Example 3.14: Saving and Loading energy tables

// Continue from example 3.13

// Save the energy table to disk
energyTable.Write("myTable.gz");

// Load the energy table from disk
energyTable.Load("myTable.gz");

The above code will write the energy table to a file called "myTable.gz" and then load it again from the same file.