source: ThirdParty/mpqc_open/src/lib/math/optimize/steep.cc@ 860145

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 860145 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 6.6 KB
Line 
1//
2// steep.cc --- implementation of steepest descent
3//
4// Copyright (C) 1997 Limit Point Systems, Inc.
5//
6// Author: Edward Seidl <seidl@janed.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <math.h>
33#include <float.h>
34
35#include <util/state/stateio.h>
36#include <math/optimize/steep.h>
37#include <util/keyval/keyval.h>
38#include <util/misc/formio.h>
39
40using namespace std;
41using namespace sc;
42
43/////////////////////////////////////////////////////////////////////////
44// SteepestDescentOpt
45
46static ClassDesc SteepestDescentOpt_cd(
47 typeid(SteepestDescentOpt),"SteepestDescentOpt",2,"public Optimize",
48 0, create<SteepestDescentOpt>, create<SteepestDescentOpt>);
49
50SteepestDescentOpt::SteepestDescentOpt(const Ref<KeyVal>&keyval):
51 Optimize(keyval),
52 maxabs_gradient(-1.0)
53{
54 lineopt_ << keyval->describedclassvalue("lineopt");
55 accuracy_ = keyval->doublevalue("accuracy");
56 if (keyval->error() != KeyVal::OK) accuracy_ = 0.0001;
57 print_x_ = keyval->booleanvalue("print_x");
58 print_gradient_ = keyval->booleanvalue("print_gradient");
59}
60
61SteepestDescentOpt::SteepestDescentOpt(StateIn&s):
62 SavableState(s),
63 Optimize(s)
64{
65 s.get(accuracy_);
66 s.get(take_newton_step_);
67 s.get(maxabs_gradient);
68 s.get(print_x_);
69 s.get(print_gradient_);
70 lineopt_ << SavableState::restore_state(s);
71}
72
73SteepestDescentOpt::~SteepestDescentOpt()
74{
75}
76
77void
78SteepestDescentOpt::save_data_state(StateOut&s)
79{
80 Optimize::save_data_state(s);
81 s.put(accuracy_);
82 s.put(take_newton_step_);
83 s.put(maxabs_gradient);
84 s.put(print_x_);
85 s.put(print_gradient_);
86 SavableState::save_state(lineopt_.pointer(),s);
87}
88
89void
90SteepestDescentOpt::init()
91{
92 Optimize::init();
93 take_newton_step_ = 1;
94 maxabs_gradient = -1.0;
95}
96
97int
98SteepestDescentOpt::update()
99{
100 // these are good candidates to be input options
101 const double maxabs_gradient_to_desired_accuracy = 0.05;
102 const double maxabs_gradient_to_next_desired_accuracy = 0.005;
103 const double roundoff_error_factor = 1.1;
104
105 // the gradient convergence criterion.
106 double old_maxabs_gradient = maxabs_gradient;
107 RefSCVector xcurrent;
108 RefSCVector gcurrent;
109
110 // get the next gradient at the required level of accuracy.
111 // usually only one pass is needed, unless we happen to find
112 // that the accuracy was set too low.
113 int accurate_enough;
114 do {
115 // compute the current point
116 function()->set_desired_gradient_accuracy(accuracy_);
117
118 xcurrent = function()->get_x();
119 gcurrent = function()->gradient().copy();
120
121 // compute the gradient convergence criterion now so i can see if
122 // the accuracy needs to be tighter
123 maxabs_gradient = gcurrent.maxabs();
124 // compute the required accuracy
125 accuracy_ = maxabs_gradient * maxabs_gradient_to_desired_accuracy;
126
127 if (accuracy_ < DBL_EPSILON) accuracy_ = DBL_EPSILON;
128
129 // The roundoff_error_factor is thrown in to allow for round off making
130 // the current gcurrent.maxabs() a bit smaller than the previous,
131 // which would make the current required accuracy less than the
132 // gradient's actual accuracy and cause everything to be recomputed.
133 accurate_enough = (
134 function()->actual_gradient_accuracy()
135 <= accuracy_*roundoff_error_factor);
136
137 if (!accurate_enough) {
138 ExEnv::out0().unsetf(ios::fixed);
139 ExEnv::out0() << indent
140 << "NOTICE: function()->actual_gradient_accuracy() > accuracy_:\n"
141 << indent
142 << scprintf(
143 " function()->actual_gradient_accuracy() = %15.8e",
144 function()->actual_gradient_accuracy()) << endl << indent
145 << scprintf(
146 " accuracy_ = %15.8e",
147 accuracy_) << endl;
148 }
149 } while(!accurate_enough);
150
151 if (old_maxabs_gradient >= 0.0 && old_maxabs_gradient < maxabs_gradient) {
152 ExEnv::out0() << indent
153 << scprintf("NOTICE: maxabs_gradient increased from %8.4e to %8.4e",
154 old_maxabs_gradient, maxabs_gradient) << endl;
155 }
156
157 // make the next gradient computed more accurate, since it will
158 // be smaller
159 accuracy_ = maxabs_gradient * maxabs_gradient_to_next_desired_accuracy;
160
161 if (!take_newton_step_ && lineopt_.nonnull()) {
162 // see if the line min step is really needed
163// if (line min really needed) {
164// take_newton_step_ = (lineopt_->update() == 1);
165// // maybe check for convergence and return here
166// }
167 }
168
169 if (print_x_) {
170 int n = xcurrent.n();
171 ExEnv::out0() << indent << "x = [";
172 for (int i=0; i<n; i++) {
173 ExEnv::out0() << scprintf(" % 16.12f",double(xcurrent(i)));
174 }
175 ExEnv::out0() << " ]" << endl;
176 }
177
178 if (print_gradient_) {
179 int n = gcurrent.n();
180 ExEnv::out0() << indent << "gradient = [";
181 for (int i=0; i<n; i++) {
182 ExEnv::out0() << scprintf(" % 16.12f",double(gcurrent(i)));
183 }
184 ExEnv::out0() << " ]" << endl;
185 }
186
187 // take the step
188 RefSCVector xdisp = -1.0*gcurrent;
189
190 // scale the displacement vector if it's too large
191 double tot = sqrt(xdisp.scalar_product(xdisp));
192 if (tot > max_stepsize_) {
193 double scal = max_stepsize_/tot;
194 ExEnv::out0() << endl << indent
195 << scprintf("stepsize of %f is too big, scaling by %f",tot,scal)
196 << endl;
197 xdisp.scale(scal);
198 tot *= scal;
199 }
200
201 ExEnv::out0() << endl << indent
202 << scprintf("taking step of size %f", tot) << endl;
203
204 RefSCVector xnext = xcurrent + xdisp;
205
206 conv_->reset();
207 conv_->get_grad(function());
208 conv_->get_x(function());
209 conv_->set_nextx(xnext);
210
211 function()->set_x(xnext);
212
213 // do a line min step next time
214 if (lineopt_.nonnull()) take_newton_step_ = 0;
215
216 return conv_->converged();
217}
218
219/////////////////////////////////////////////////////////////////////////////
220
221// Local Variables:
222// mode: c++
223// c-file-style: "ETS"
224// End:
Note: See TracBrowser for help on using the repository browser.