Xmipp  v3.23.11-Nereus
Poly.cpp
Go to the documentation of this file.
1 /*
2 
3 CONDOR 1.06 - COnstrained, Non-linear, Direct, parallel Optimization
4  using trust Region method for high-computing load,
5  noisy functions
6 Copyright (C) 2004 Frank Vanden Berghen
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation version 2
11 of the License.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 
22 If you want to include this tools in any commercial product,
23 you can contact the author at fvandenb@iridia.ulb.ac.be
24 
25 */
26 
27 #include <stdio.h>
28 #include <memory.h>
29 //#include <crtdbg.h>
30 #include "Vector.h"
31 #include "MultInd.h"
32 #include "tools.h"
33 #include "Poly.h"
34 #include "IntPoly.h"
35 
36 const unsigned int Polynomial::NicePrint = 1;
37 const unsigned int Polynomial::Warning = 2;
38 const unsigned int Polynomial::Normalized= 4; // Use normalized monomials
40 
42 
43 void Polynomial::init(int _dim, int _deg, double *data)
44 {
45  int n;
46  d=(PolynomialData*)malloc(sizeof(PolynomialData));
47  if (_dim) n=d->n=choose( _dim+_deg, _dim );
48  else n=d->n=0;
49 
50  d->dim=_dim;
51  d->deg=_deg;
52  d->ref_count=1;
53 
54  if (n==0) { d->coeff=NULL; return; };
55 
56  d->coeff=(double*)malloc(n*sizeof(double));
57  if (d->coeff==NULL) { printf("memory allocation error\n"); getchar(); exit(253); }
58 
59  if (data) memcpy(d->coeff, data, d->n*sizeof(double));
60  else memset(d->coeff, 0, d->n*sizeof(double));
61 }
62 /*
63 Polynomial::PolyInit( const Polynomial& p )
64 { dim = p.dim; deg = p.deg; coeff=((Vector)p.coeff).clone(); }
65 */
66 Polynomial::Polynomial( unsigned Dim, unsigned Deg, double *data )
67 {
68  init(Dim,Deg,data);
69 }
70 
71 Polynomial::Polynomial( unsigned Dim, double val ) // Constant polynomial
72 {
73  init(Dim,0,&val);
74 }
75 
77 {
78  init(I.dim,I.len());
79  d->coeff[I.index()] = 1;
80 }
81 
83 {
85 }
86 
88 {
89  if (!d) return;
90  (d->ref_count) --;
91  if (d->ref_count==0)
92  {
93  if (d->coeff) free(d->coeff);
94  free(d);
95  }
96 }
97 
99 {
100  // shallow copy
101  if (this != &A)
102  {
104  d=A.d;
105  (d->ref_count) ++ ;
106  }
107  return *this;
108 }
109 
111 {
112  // shallow copy
113  d=A.d;
114  (d->ref_count)++ ;
115 }
116 
118 {
119  // a deep copy
120  Polynomial m(d->dim,d->deg);
121  m.copyFrom(*this);
122  return m;
123 }
124 
126 {
127  if (m.d->dim!=d->dim)
128  {
129  printf("poly: copyFrom: dim do not agree");
130  getchar(); exit(254);
131  }
132 
133  d->deg = mmax(d->deg,m.d->deg); // New degree
134  unsigned N1=sz(), N2=m.sz();
135  if (N1!=N2)
136  {
137  d->coeff=(double*)realloc(d->coeff,N2*sizeof(double));
138  d->n=m.d->n;
139  }
140  memcpy((*this),m,N2*sizeof(double));
141 }
142 
144 {
145  int i=sz();
146  Polynomial q( d->dim, d->deg );
147  double *tq = q.d->coeff, *tp = d->coeff;
148 
149  while (i--) *(tq++) = *(tp++) * t;
150  return q;
151 }
152 
153 
155 {
156  if (t == 0)
157  {
158  printf( "op/(Poly,double): Division by zero\n");
159  getchar(); exit(-1);
160  }
161  int i=sz();
162  Polynomial q( d->dim, d->deg );
163  double *tq = q.d->coeff, *tp = d->coeff;
164 
165  while (i--) *(tq++) = *(tp++) / t;
166  return q;
167 }
168 
170 {
171  if (d->dim != q.d->dim)
172  {
173  printf( "Poly::op+ : Different dimension\n");
174  getchar(); exit(-1);
175  }
176 
177  Polynomial r(d->dim,mmax(d->deg,q.d->deg));
178  unsigned N1=sz(), N2=q.sz(), Ni=mmin(N1,N2);
179  double *tr = r, *tp = (*this), *tq = q;
180  while (Ni--) *(tr++) = *(tp++) + *(tq++);
181  if (N1<N2)
182  {
183  memcpy(tr,tq,(N2-N1)*sizeof(double));
184 // N2-=N1; while (N2--) *(tr++)=*(tq++);
185  }
186  return r;
187 }
188 
189 
191 {
192  if (d->dim != q.d->dim)
193  {
194  printf("Poly::op- : Different dimension\n");
195  getchar(); exit(-1);
196  }
197 
198  Polynomial r(d->dim,mmax(d->deg,q.d->deg));
199  unsigned N1=sz(), N2=q.sz(), Ni=mmin(N1,N2);
200  double *tr = r, *tp = (*this), *tq = q;
201  while (Ni--) *(tr++) = *(tp++) - *(tq++);
202  if (N1<N2)
203  {
204  N2-=N1; while (N2--) *(tr++)=-(*(tq++));
205  }
206  return r;
207 }
208 
210 {
211  unsigned Ni = sz();
212  double *tp = (*this);
213 
214  if (!Ni || !tp) return *this; // Take it like it is ...
215 
216  Polynomial r(d->dim,d->deg);
217  double *tq = (r);
218  while( Ni-- ) *(tq++) = -(*(tp++));
219  return r;
220 }
221 
222 
224 {
225  if (d->dim != p.d->dim)
226  {
227  printf("Poly::op+= : Different dimension\n");
228  getchar(); exit(-1);
229  }
230 
231  d->deg = mmax(d->deg,p.d->deg); // New degree
232  unsigned N1=sz(), N2=p.sz(), Ni=mmin(N1,N2);
233  if (N1<N2)
234  {
235  d->coeff=(double*)realloc(d->coeff,N2*sizeof(double));
236  d->n=p.d->n;
237  }
238  double *tt = (*this),*tp = p;
239 
240  while (Ni--) *(tt++) += *(tp++);
241 
242  if (N1<N2)
243  {
244  memcpy(tt,tp,(N2-N1)*sizeof(double));
245 // N2-=N1; while (N2--) *(tt++)=*(tp++);
246  }
247 
248  return *this;
249 }
250 
251 
253 {
254  if (d->dim != p.d->dim)
255  {
256  printf( "Poly::op-= : Different dimension\n");
257  getchar(); exit(-1);
258  }
259 
260  d->deg = mmax(d->deg,p.d->deg); // New degree
261  unsigned N1=sz(), N2=p.sz(), Ni=mmin(N1,N2);
262  if (N1<N2)
263  {
264  d->coeff=(double*)realloc(d->coeff,N2*sizeof(double));
265  d->n=p.d->n;
266  }
267  double *tt = (*this),*tp = p;
268 
269  while (Ni--) *(tt++) -= *(tp++);
270 
271  if (N1<N2)
272  {
273  N2-=N1; while (N2--) *(tt++)=-(*(tp++));
274  }
275 
276  return *this;
277 }
278 
279 
281 {
282  int i=sz();
283  double *tp = (*this);
284 
285  while (i--) *(tp++) *=t;
286  return *this;
287 }
288 
289 
291 {
292  if (t == 0)
293  {
294  printf( "Poly::op/= : Division by zero\n");
295  getchar(); exit(-1);
296  }
297 
298  int i=sz();
299  double *tp = (*this);
300 
301  while (i--) *(tp++) /=t;
302  return *this;
303 }
304 
306 {
307  if (d==q.d) return 1;
308  if ( (d->deg != q.d->deg) || (d->dim != q.d->dim) ) return 0;
309 
310  unsigned N = sz();
311  double *tp = (*this),*tq = q;
312 
313  while (N--)
314  if ( *(tp++) != *(tq++) ) return 0;
315 
316  return 1;
317 }
318 
319 //ostream& Polynomial::PrintToStream( ostream& out ) const
321 {
322  MultInd I( d->dim );
323  double *tt = (*this);
324  unsigned N = sz();
325  bool IsFirst=true;
326 
327  if ( !N || !tt ) { printf("[Void polynomial]\n"); return; }
328 
329  if (*tt) { IsFirst=false; printf("%f", *tt); }
330  tt++; ++I;
331 
332  for (unsigned i = 1; i < N; i++,tt++,++I)
333  {
334  if (*tt != 0)
335  {
336  if (IsFirst)
337  {
338  if (queryFlag( NicePrint ))
339  {
340  if (*tt<0) printf("-");
341  printf("%f x^",condorAbs(*tt)); I.print();
342  }
343  else
344  {
345  printf("+%f x^",*tt); I.print();
346  }
347  IsFirst = false;
348  continue;
349  }
350  if (queryFlag( NicePrint ))
351  {
352  if (*tt<0) printf("-"); else printf("+");
353  printf("%f x^",condorAbs(*tt)); I.print();
354  }
355  else
356  {
357  printf("+%f x^",*tt); I.print();
358  }
359 
360  }
361  }
362 }
363 
364 /*
365 double Polynomial::simpleEval(Vector P)
366 {
367  unsigned i=coeff.sz(),j;
368  double *cc=coeff,r=0, r0, *p=(double*)P;
369  MultInd I(dim);
370  while (i--)
371  {
372  r0=*(cc++); j=dim;
373  while (j--) r0*=pow(p[j],I[j]);
374  r+=r0; I++;
375  }
376  return r;
377 }
378 */
379 
380 double Polynomial::shiftedEval( Vector Point, double minusVal)
381 {
382  double tmp1=d->coeff[0], tmp2;
383  d->coeff[0]-=minusVal;
384  tmp2=(*this)(Point);
385  d->coeff[0]=tmp1;
386  return tmp2;
387 }
388 
389 // Evaluation oprator
390 // According to Pena, Sauer, "On the multivariate Horner scheme",
391 // SIAM J. Numer. Anal., to appear
392 
394 {
395 // I didn't notice any difference in precision:
396 // return simpleEval(P);
397 
398  unsigned dim=d->dim, deg=d->deg;
399  double r,r0; // no static here because of the 2 threads !
400  double rbuf[100]; // That should suffice // no static here because of the 2 threads !
401  double *rbufp = rbuf;
402  unsigned lsize = 100;
403  double *rptr;
404  int i,j;
405 
406  if (Point==Vector::emptyVector) return *d->coeff;
407  if (deg==0) return *d->coeff;
408 
409  if ( dim != (unsigned)Point.sz() )
410  {
411  printf( "Polynomial::operator()( Vector& ) : Improper size\n");
412  getchar(); exit(-1);
413  }
414 
415  if ( !sz() )
416  {
417  if ( queryFlag( Warning ) )
418  {
419  printf( "Polynomial::operator()( Vector& ) : evaluating void polynomial\n");
420  }
421  return 0;
422  }
423 
424  if ( dim > lsize ) // Someone must be crazy !!!
425  {
426  if ( queryFlag( Warning ) )
427  {
428  printf( "Polynomial::operator()( Vector& ) : Warning -> 100 variables\n");
429  }
430 
431  lsize=dim;
432  rbufp = (double*)malloc(lsize*sizeof(double)); // So be it ...
433 
434  if ( !rbufp )
435  {
436  printf( "Polynomial::operator()( Vector& ) : Cannot allocate <rbufp>\n");
437  getchar(); exit( -1 );
438  }
439  }
440 
441  // Initialize
442  MultInd *mic=cacheMultInd.get( dim, deg );
443  unsigned *nextI=mic->indexesOfCoefInLexOrder(),
444  *lcI=mic->lastChanges();
445  double *cc = (*this), *P=Point;
446  unsigned nxt, lc;
447 
448  // Empty buffer (all registers = 0)
449  memset(rbufp,0,dim*sizeof(double));
450 
451  r0=cc[*(nextI++)];
452  i=sz()-1;
453  while (i--)
454  {
455  nxt= *(nextI++);
456  lc = *(lcI++);
457 
458  r=r0; rptr=rbufp+lc; j=dim-lc;
459  while (j--) { r+=*rptr; *(rptr++)=0; }
460  rbufp[lc]=P[lc]*r;
461  r0=cc[nxt];
462  }
463  r=r0; rptr=rbufp; i=(int)dim;
464  while (i--) r+=*(rptr++);
465 
466  return r;
467 }
468 
470 {
471  unsigned dim=d->dim, deg=d->deg;
472  if (deg<1) return Polynomial(dim,0.0);
473 
474  Polynomial r(dim, deg-1);
475  MultInd I( dim );
476  MultInd J( dim );
477  double *tS=(*this), *tD=r;
478  unsigned j=sz(), k, *cc, sum,
479  *allExpo=(unsigned*)I, *expo=allExpo+i, *firstOfJ=(unsigned*)J;
480 
481  while (j--)
482  {
483  if (*expo)
484  {
485  (*expo)--;
486 
487  sum=0; cc=allExpo; k=dim;
488  while (k--) sum+=*(cc++);
489  if (sum) k=choose( sum-1+dim, dim ); else k=0;
490  J.resetCounter(); *firstOfJ=sum;
491  while (!(J==I)) { k++; J++; }
492 
493  (*expo)++;
494  tD[k]=(*tS) * (double)*expo;
495  }
496  tS++;
497  I++;
498  }
499  return r;
500 }
501 
503 {
504  unsigned i=d->dim;
505  G.setSize(i);
506  double *r=G;
508  {
509  memcpy(r,d->coeff+1,i*sizeof(double));
510  return;
511  }
512  while (i--) r[i]=(derivate(i))(P);
513 }
514 
516 {
517  unsigned dim=d->dim;
518  G.setSize(dim);
519  H.setSize(dim,dim);
520  double *r=G, **h=H;
521  unsigned i,j;
522 
523  if (d->deg==2)
524  {
525  double *c=d->coeff+1;
526  memcpy(r,c,dim*sizeof(double));
527  c+=dim;
528  for (i=0; i<dim; i++)
529  {
530  h[i][i]=2* *(c++);
531  for (j=i+1; j<dim; j++)
532  h[i][j]=h[j][i]=*(c++);
533  }
534  if (P.equals(Vector::emptyVector)) return;
535  G+=H.multiply(P);
536  return;
537  }
538 
539  Polynomial *tmp=new Polynomial[dim], a;
540  i=dim;
541  while (i--)
542  {
543  tmp[i]=derivate(i);
544  r[i]=(tmp[i])(P);
545  }
546 
547  i=dim;
548  while (i--)
549  {
550  j=i+1;
551  while (j--)
552  {
553  a=tmp[i].derivate(j);
554  h[i][j]=h[j][i]=a(P);
555  }
556  }
557 
558 // _CrtCheckMemory();
559 
560  delete []tmp;
561 }
562 
563 void Polynomial::translate(Vector translation)
564 {
565  if (d->deg>2)
566  {
567  printf("Translation only for polynomial of degree lower than 3.\n");
568  getchar(); exit(255);
569  }
570  d->coeff[0]=(*this)(translation);
571  if (d->deg==1) return;
572  int dim=d->dim;
573  Vector G(dim);
574  Matrix H(dim,dim);
575  gradientHessian(translation, G, H);
576  memcpy(((double*)d->coeff)+1, (double*)G, dim*sizeof(double));
577 }
578 
579 void Polynomial::save(char *name)
580 {
581  std::ofstream ofp(name, std::ios::out | std::ios::binary);
582  ofp.write(reinterpret_cast<const char*>(&d->dim), sizeof(int));
583  ofp.write(reinterpret_cast<const char*>(&d->deg), sizeof(int));
584  ofp.write(reinterpret_cast<const char*>(d->coeff), d->n*sizeof(double));
585  ofp.close();
586 }
587 
589 {
590  unsigned _dim,_deg;
591  std::ifstream ifp(name, std::ios::in | std::ios::binary);
592  ifp.read(reinterpret_cast<char*>(&_dim), sizeof(int));
593  ifp.read(reinterpret_cast<char*>(&_deg), sizeof(int));
594  init(_dim,_deg);
595  ifp.read(reinterpret_cast<char*>(d->coeff), d->n*sizeof(double));
596  ifp.close();
597 }
static const unsigned int Warning
Definition: Poly.h:118
unsigned sz()
Definition: Poly.h:64
unsigned long choose(unsigned n, unsigned k)
Definition: tools.cpp:38
MultIndCache cacheMultInd
Definition: MultInd.cpp:42
int equals(Polynomial q)
Definition: Poly.cpp:305
void translate(Vector translation)
Definition: Poly.cpp:563
int * mmax
doublereal * c
void print()
Definition: Poly.cpp:320
Matrix multiply(Matrix B)
Definition: Matrix.cpp:633
unsigned * lastChanges()
Definition: MultInd.cpp:204
Polynomial operator-=(Polynomial)
Definition: Poly.cpp:252
Definition: Vector.h:37
unsigned dim()
Definition: Poly.h:62
static unsigned int flags
Definition: Poly.h:121
int equals(const Vector Q)
Definition: Vector.cpp:135
static const unsigned int Normalized
Definition: Poly.h:119
Polynomial & operator=(const Polynomial &A)
Definition: Poly.cpp:98
double mmin(const double t1, const double t2)
Definition: tools.h:69
MultInd * get(unsigned _dim, unsigned _deg)
Definition: MultInd.cpp:242
Polynomial operator/(const double)
Definition: Poly.cpp:154
unsigned deg()
Definition: Poly.h:63
void setSize(int _nLine, int _nColumn)
Definition: Matrix.cpp:205
Definition: point.h:32
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void setSize(int _n)
Definition: Vector.cpp:112
Polynomial operator*=(const double)
Definition: Poly.cpp:280
unsigned sz()
Definition: Vector.h:79
static const unsigned int NicePrint
Definition: Poly.h:117
Polynomial operator*(const double)
Definition: Poly.cpp:143
int in
void gradientHessian(Vector P, Vector G, Matrix H)
Definition: Poly.cpp:515
double operator()(Vector)
Definition: Poly.cpp:393
void init(int _dim, int _deg, double *data=NULL)
Definition: Poly.cpp:43
double condorAbs(const double t1)
Definition: tools.h:47
free((char *) ob)
unsigned len()
Definition: MultInd.cpp:96
Definition: Matrix.h:38
Polynomial clone()
Definition: Poly.cpp:117
Polynomial derivate(int i)
Definition: Poly.cpp:469
Polynomial operator+(void)
Definition: Poly.h:84
#define j
int m
unsigned index()
Definition: MultInd.h:68
~Polynomial()
Definition: Poly.cpp:82
PolynomialData * d
Definition: Poly.h:49
unsigned * indexesOfCoefInLexOrder()
Definition: MultInd.cpp:214
void resetCounter()
Definition: MultInd.cpp:164
static Vector emptyVector
Definition: Vector.h:119
void save(char *name)
Definition: Poly.cpp:579
unsigned dim
Definition: MultInd.h:53
double shiftedEval(Vector Point, double minusVal)
Definition: Poly.cpp:380
void print()
Definition: MultInd.cpp:86
void gradient(Vector P, Vector G)
Definition: Poly.cpp:502
Polynomial operator-(void)
Definition: Poly.cpp:209
Polynomial operator+=(Polynomial)
Definition: Poly.cpp:223
unsigned queryFlag(unsigned int val)
Definition: Poly.h:124
void copyFrom(Polynomial a)
Definition: Poly.cpp:125
static Polynomial emptyPolynomial
Definition: Poly.h:126
int * n
Polynomial()
Definition: Poly.h:54
doublereal * a
void destroyCurrentBuffer()
Definition: Poly.cpp:87
Polynomial operator/=(const double)
Definition: Poly.cpp:290