View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.numerics;
39  
40  import java.util.Collections;
41  import java.util.List;
42  
43  /**
44   * The OptimizationInterface defines methods required by an optimizer.
45   *
46   * @author Michael J. Schnieders
47   * @since 1.0
48   */
49  public interface OptimizationInterface {
50  
51    /**
52     * Destroys this Potential and frees up any associated resources, particularly worker Threads.
53     * Default implementation is to return true (assume destruction successful).
54     *
55     * @return If resource reclamation successful, or resources already reclaimed.
56     */
57    default boolean destroy() {
58      return true;
59    }
60  
61    /**
62     * This method is called repeatedly to compute the function energy.
63     *
64     * @param x Input parameters.
65     * @return Function value at <code>x</code>.
66     * @since 1.0
67     */
68    double energy(double[] x);
69  
70    /**
71     * This method is called repeatedly to compute the function energy. The verbose flag may not be
72     * used by all implementations.
73     *
74     * @param x       Input parameters.
75     * @param verbose Display extra information.
76     * @return Function value at <code>x</code>
77     */
78    default double energy(double[] x, boolean verbose) {
79      return energy(x);
80    }
81  
82    /**
83     * This method is called repeatedly to compute the function energy and gradient.
84     *
85     * @param x Input parameters.
86     * @param g Output gradients with respect to each parameter.
87     * @return Function value at <code>x</code>.
88     * @since 1.0
89     */
90    double energyAndGradient(double[] x, double[] g);
91  
92    /**
93     * This method is called repeatedly to compute the function energy and gradient. The verbose flag
94     * may not be used by all implementations.
95     *
96     * @param x       Input parameters.
97     * @param g       Output gradients with respect to each parameter.
98     * @param verbose Display extra information.
99     * @return Function value at <code>x</code>.
100    * @since 1.0
101    */
102   default double energyAndGradient(double[] x, double[] g, boolean verbose) {
103     return energyAndGradient(x, g);
104   }
105 
106   /**
107    * Load the current value of the parameters. If the supplied array is null or not large enough, a
108    * new one should be created. The filled array is returned.
109    *
110    * @param parameters Supplied array.
111    * @return The array filled with parameter values.
112    */
113   double[] getCoordinates(double[] parameters);
114 
115   /**
116    * Get the number of variables being operated on.
117    *
118    * @return Number of variables.
119    */
120   int getNumberOfVariables();
121 
122   /**
123    * Get the problem scaling.
124    *
125    * @return The scaling value used for each variable.
126    * @since 1.0
127    */
128   double[] getScaling();
129 
130   /**
131    * Scale the problem. A good choice for optimization is the square root of the median eigenvalue of
132    * a typical Hessian.
133    *
134    * @param scaling The scaling value to use for each variable.
135    * @since 1.0
136    */
137   void setScaling(double[] scaling);
138 
139   /**
140    * Get the total energy of the system
141    *
142    * @return the total energy
143    */
144   double getTotalEnergy();
145 
146   /**
147    * Returns a List of Potentials this Potential depends on with a recursive search, excluding the
148    * top level of this call. May not be implemented for all Potentials.
149    *
150    * @return By default, an empty list.
151    */
152   default List<Potential> getUnderlyingPotentials() {
153     return Collections.emptyList();
154   }
155 
156   /**
157    * Default method to scale coordinates.
158    *
159    * @param x Input parameters.
160    */
161   default void scaleCoordinates(double[] x) {
162     double[] scaling = getScaling();
163     if (scaling != null) {
164       int nParams = x.length;
165       for (int i = 0; i < nParams; i++) {
166         x[i] *= scaling[i];
167       }
168     }
169   }
170 
171   /**
172    * Default method to unscale coordinates.
173    *
174    * @param x Input parameters.
175    * @param g Gradient array.
176    */
177   default void scaleCoordinatesAndGradient(double[] x, double[] g) {
178     double[] scaling = getScaling();
179     if (scaling != null) {
180       int len = x.length;
181       for (int i = 0; i < len; i++) {
182         x[i] *= scaling[i];
183         g[i] /= scaling[i];
184       }
185     }
186   }
187 
188   /**
189    * Default method to unscale coordinates.
190    *
191    * @param x Input parameters.
192    */
193   default void unscaleCoordinates(double[] x) {
194     double[] scaling = getScaling();
195     if (scaling != null) {
196       int nParams = x.length;
197       for (int i = 0; i < nParams; i++) {
198         x[i] /= scaling[i];
199       }
200     }
201   }
202 }