Points&Forces (core)
Software tools facilitating the task of surveying architecture
a_fn.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2011-2019 Pierre SMARS (smars@yuntech.edu.tw)
3  This program is free software: you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation, either version 2 of the License, or
6  (at your option) any later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 #include "a_fn.h"
17 #include "a_mat_sq.h"
18 #include "a_mat_c.h"
19 #include "a_mat_r.h"
20 
21 // .PORTABILITY : ansi C++
22 
23 //---------------------------------------------------------------------------
24 a_fn::a_fn(int nv, double dmin, double gmin) : nv_(nv), dmin_(dmin), gmin_(gmin)
25 {
26  x_ = new a_mat_c(nv_);
27  x0_ = new a_mat_c(nv_);
28 }
29 //---------------------------------------------------------------------------
31 {
32  delete x_;
33 }
34 //---------------------------------------------------------------------------
35 void a_fn::showX(std::ostream& o)
36 {
37  if (nv_==1)
38  o << (*x_)(0) << std::endl;
39  else
40  {
41  for (int i = 0; i < nv_-1; i++)
42  o << (*x_)(i) << " ";
43  o << (*x_)(nv_-1) << std::endl;
44  }
45 }
46 //---------------------------------------------------------------------------
47 void a_fn::setX(const a_mat_c& x)
48 {
49  for (int i = 0; i < nv_; i++)
50  (*x_)(i) = x(i);
51 }
52 //---------------------------------------------------------------------------
53 double a_fn::getdF(int ai)
54 {
55  double p0 = (*x_)(ai);
56  (*x_)(ai) = 0.;
57  (*x_)(ai) = p0-dmin_/2.;
58  double Fmin = this->getF();
59  (*x_)(ai) = p0+dmin_/2.;
60  double Fmax = this->getF();
61  (*x_)(ai) = p0;
62  return (Fmax-Fmin)/dmin_;
63 }
64 //---------------------------------------------------------------------------
66 {
67  for (int i = 0; i < nv_; i++)
68  grad(i) = this->getdF(i);
69 }
70 //---------------------------------------------------------------------------
71 void a_fn::dx(int ai)
72 {
73  double ax = this->getX(ai);
74  double dfp = this->getdF(ai);
75  double fp = this->getF();
76  (*x_)(ai) = ax-fp/dfp;
77 }
78 //---------------------------------------------------------------------------
79 void a_fn::newton(int ai)
80 {
81  double f0 = this->getF();
82  double df = this->getdF(ai);
83  if (df != 0)
84  {
85  do
86  {
87  this->dx(ai);
88  double f = this->getF();
89  df = fabs(f0-f);
90  f0 = f;
91  }
92  while (df>dmin_);
93  }
94 }
95 //---------------------------------------------------------------------------
96 void a_fn::incr(double alpha, const a_mat_c& dir)
97 {
98  for (int i = 0; i < nv_; i++)
99  (*x_)(i) += dir(i)*alpha;
100 }
101 //---------------------------------------------------------------------------
102 void a_fn::go(double alpha, const a_mat_c& dir)
103 {
104  for (int i = 0; i < nv_; i++)
105  (*x_)(i) = (*x0_)(i) + dir(i)*alpha;
106  /* if (alpha != alpha0_)
107  {
108  this->incr(alpha-alpha0_,dir);
109  alpha0_ = alpha;
110  }*/
111 }
112 //---------------------------------------------------------------------------
113 double a_fn::gF(double alpha, const a_mat_c& dir)
114 {
115  this->go(alpha,dir);
116  return this->getF();
117 }
118 //---------------------------------------------------------------------------
119 void a_fn::minGold0(const a_mat_c& dir, double A1, double B1)
120 {
121  double f0 = this->getF();
122  const double p = 0.381966011249;
123  double crit0 = (B1-A1)/1.e10;
124  bool t1 = true;
125  bool t2 = true;
126  this->setx0();
127  double x1,x2;
128  do
129  {
130  std::cout << ".";
131  double f1,f2;
132  double L1 = B1-A1;
133  double L2 = p*L1;
134  if (t1)
135  {
136  x1 = A1+L2;
137  f1 = this->gF(x1,dir);
138  }
139  if (t2)
140  {
141  x2 = B1-L2;
142  f2 = this->gF(x2,dir);
143  }
144  if (f1<f2)
145  {
146  B1 = x2;
147  x2 = x1;
148  f2 = f1;
149  t1 = true; t2 = false;
150  }
151  else if (f1==f2)
152  {
153  A1= x1;
154  B1 = x2;
155  t1 = true; t2 = true;
156  }
157  else
158  {
159  A1 = x1;
160  x1 = x2;
161  f1 = f2;
162  t1 = false; t2 = true;
163  }
164  }
165  while (B1-A1>crit0);
166  // this->go(A1,dir);
167  double f = this->getF();
168  if (f>f0)
169  {
170  std::cout << "f>f0 !!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
171  this->go(0,dir);
172  }
173 }
174 //---------------------------------------------------------------------------
175 void a_fn::minGold(const a_mat_c& dir)
176 {
177  double f0 = this->getF();
178  this->setx0();
179  int k = -1;
180  int iter;
181  double di0 = 0.1;
182  double i,di;
183  double prov = 0;
184  do
185  {
186  k++;
187  // this->go(0,dir);
188  iter = 0;
189  double f0;
190  double f = this->gF(0,dir);
191  i = 0;
192  di = di0*exp(k*log(0.1));
193  // std::cout << "di: " << di << std::endl;
194  do
195  {
196  // std::cout << "ok" << std::endl;
197  iter++;
198  di *= 2.;
199  i += di;
200  f0 = f;
201  f = this->gF(i,dir);
202  }
203  while (f<=f0);
204  if (iter ==1 ) prov++;
205  }
206  while (iter<4);
207  double A1 = i-di-di/2.;
208  double B1 = i;
209  std::cout << "A1: " << A1 << " B1: " << B1 << std::endl;
210  this->go(A1,dir);
211  double f = this->getF();
212  if (f>f0)
213  {
214  std::cout << "minGold----------------------------" << std::endl;
215  // std::cout << "f-f0: " << f-f0 << std::endl;
216  // std::cout << "A1: " << A1 << " B1: " << B1 << std::endl;
217  }
218  f0 = f;
219  this->minGold0(dir,0,B1-A1);
220  f = this->getF();
221  if (f>f0)
222  std::cout << "minGold0++++++++++++++++++++++++++++" << std::endl;
223 }
224 //---------------------------------------------------------------------------
226 {
227  auto dir = new a_mat_c(nv_);
228  do
229  {
230  this->getGrad(*dir);
231  dir->normalise();
232  *dir *= -1;
233  this->minGold(*dir);
234  std::cout << "f: " << this->getF() << std::endl;
235  }
236  while (!this->minver());
237  delete dir;
238 }
239 //---------------------------------------------------------------------------
241 {
242  auto dir = new a_mat_c(nv_);
243  do
244  {
245  for (int j = 0; j < nv_; j++)
246  {
247  if (this->getdF(j)>0)
248  (*dir)(j) = -1;
249  else
250  (*dir)(j) = 1;
251  this->minGold(*dir);
252  (*dir)(j) = 0;
253  }
254  }
255  while (!this->minver());
256  delete dir;
257 }
258 //---------------------------------------------------------------------------
260 {
261  auto dir = new a_mat_c(nv_);
262  this->getGrad(*dir);
263  double test = sqrt(dir->sumsq()/nv_);
264  delete dir;
265  return (test<gmin_);
266 }
267 //***************************************************************************
268 //---------------------------------------------------------------------------
269 class a_mat_sq_DVP : public a_mat_sq
270 {
271  public:
272  a_mat_sq_DVP(UI nv);
273 };
274 //---------------------------------------------------------------------------
276 {
277  for (int i = 0; i < nv; i++)
278  (*this)(i,i) = 1;
279 }
280 //***************************************************************************
281 //---------------------------------------------------------------------------
283 {
284  auto H = new a_mat_sq_DVP(nv_);
285  a_mat_c S(nv_);
286  a_mat_c g1(nv_);
287  a_mat_c g2(nv_);
288  a_mat_sq Mi(nv_);
289  a_mat_sq Ni(nv_);
290  a_mat_r mr(nv_);
291  a_mat_sq m0(nv_);
292  a_mat_c x0(nv_);
293  a_mat_c x1(nv_);
294 
295  bool stop = false;
296  int iter = 0;
297  double f = this->getF();
298  do
299  {
300  double f0 = f;
301  iter++;
302  // if (iter==500)
303  // this->showX(std::cout);
304 
305  this->getGrad(g1);
306  S = -(*H)*g1;
307  x0 = *x_;
308  this->minGold(S);
309  f = this->getF();
310  // if (f>f0)
311  // {
312  // std::cout << "minGold---------------" << std::endl;
313  // this->showX(std::cout);
314  // }
315  std::cout << "i" << iter << " f: " << f << std::endl;
316  stop = this->minver();
317  if (!stop)
318  {
319  x1 = (*x_)-x0;
320  double d1 = sqrt(x1.sumsq()/S.sumsq());
321  this->getGrad(g2);
322  g1 = g2-g1;
323  mr = S.transpose();
324  Mi = S*mr;
325  Mi *= d1;
326  m0 = g1*mr;
327  d1 = m0(1,1);
328  if ((d1 != 0)&&(iter % 10))
329  {
330  Mi *= 1/d1;
331  //calcul de Ni
332  mr = g1.transpose();
333  g2 = (*H)*g1;
334  m0 = g2*mr;
335  d1 = m0(1,1);
336  mr = g2.transpose();
337  Ni = g2*mr;
338  if (d1 != 0)
339  Ni *= -1/d1;
340  else
341  stop = true;
342  //nouveau H
343  (*H) += Mi+Ni;
344  }
345  else
346  {
347  delete H;
348  H = new a_mat_sq_DVP(nv_);
349  }
350  }
351  }
352  while (!stop);
353  delete H;
354 }
unsigned int UI
Definition: a_mat.h:23
a_quaternion sqrt(const a_quaternion &x)
void minGold(const a_mat_c &dir)
Definition: a_fn.cxx:175
void showX(std::ostream &o)
Definition: a_fn.cxx:35
void setX(const a_mat_c &)
Definition: a_fn.cxx:47
virtual ~a_fn()
Definition: a_fn.cxx:30
void newton(int ai)
Definition: a_fn.cxx:79
bool minver()
Definition: a_fn.cxx:259
void incr(double alpha, const a_mat_c &dir)
Definition: a_fn.cxx:96
int nv_
Definition: a_fn.h:60
void dx(int ai)
Definition: a_fn.cxx:71
void setx0()
Definition: a_fn.h:66
void minsyst()
Definition: a_fn.cxx:240
void getGrad(a_mat_c &)
Definition: a_fn.cxx:65
double gmin_
Definition: a_fn.h:64
double getdF(int ai)
Definition: a_fn.cxx:53
double dmin_
Definition: a_fn.h:63
a_mat_c * getX()
Definition: a_fn.h:41
void minGold0(const a_mat_c &dir, double A1, double B1)
Definition: a_fn.cxx:119
a_mat_c * x_
Definition: a_fn.h:61
void mingrad()
Definition: a_fn.cxx:225
a_fn(int nv=1, double dmin=1.e-5, double gmin=1e-6)
Definition: a_fn.cxx:24
virtual double getF()=0
a_mat_c * x0_
Definition: a_fn.h:62
void minDFP()
Definition: a_fn.cxx:282
a column matrix unit
Definition: a_mat_c.h:29
double sumsq() const
Definition: a_mat_c.cxx:32
void normalise()
Definition: a_mat_c.cxx:45
a row matrix unit
Definition: a_mat_r.h:29
a_mat_sq_DVP(UI nv)
Definition: a_fn.cxx:275
a square matrix unit
Definition: a_mat_sq.h:29
a_mat transpose()
Definition: a_mat.cxx:127