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-2025.
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    * Set the current value of the parameters. If the supplied array is null or not large enough,
117    * no action is taken.
118    *
119    * @param parameters The array with parameter values.
120    */
121   void setCoordinates(double[] parameters);
122 
123   /**
124    * Get the number of variables being operated on.
125    *
126    * @return Number of variables.
127    */
128   int getNumberOfVariables();
129 
130   /**
131    * Get the problem scaling.
132    *
133    * @return The scaling value used for each variable.
134    * @since 1.0
135    */
136   double[] getScaling();
137 
138   /**
139    * Scale the problem. A good choice for optimization is the square root of the median eigenvalue of
140    * a typical Hessian.
141    *
142    * @param scaling The scaling value to use for each variable.
143    * @since 1.0
144    */
145   void setScaling(double[] scaling);
146 
147   /**
148    * Get the total energy of the system
149    *
150    * @return the total energy
151    */
152   double getTotalEnergy();
153 
154   /**
155    * Returns a List of Potentials this Potential depends on with a recursive search, excluding the
156    * top level of this call. May not be implemented for all Potentials.
157    *
158    * @return By default, an empty list.
159    */
160   default List<Potential> getUnderlyingPotentials() {
161     return Collections.emptyList();
162   }
163 
164   /**
165    * Default method to scale coordinates.
166    *
167    * @param x Input parameters.
168    */
169   default void scaleCoordinates(double[] x) {
170     double[] scaling = getScaling();
171     if (scaling != null) {
172       int nParams = x.length;
173       for (int i = 0; i < nParams; i++) {
174         x[i] *= scaling[i];
175       }
176     }
177   }
178 
179   /**
180    * Default method to unscale coordinates.
181    *
182    * @param x Input parameters.
183    * @param g Gradient array.
184    */
185   default void scaleCoordinatesAndGradient(double[] x, double[] g) {
186     double[] scaling = getScaling();
187     if (scaling != null) {
188       int len = x.length;
189       for (int i = 0; i < len; i++) {
190         x[i] *= scaling[i];
191         g[i] /= scaling[i];
192       }
193     }
194   }
195 
196   /**
197    * Default method to unscale coordinates.
198    *
199    * @param x Input parameters.
200    */
201   default void unscaleCoordinates(double[] x) {
202     double[] scaling = getScaling();
203     if (scaling != null) {
204       int nParams = x.length;
205       for (int i = 0; i < nParams; i++) {
206         x[i] /= scaling[i];
207       }
208     }
209   }
210 }