13 static unsigned int dim_ = 0;
14 static unsigned int max_deg_ = 0;
15 static unsigned int max_nterms_ = 0;
28 {
return {
R+Y.
R,
C+Y.
C}; }
30 {
return {
R-Y.
R,
C-Y.
C}; }
32 {
R+=Y.
R;
C+=Y.
C;
return *
this; }
34 {
R-=Y.
R;
C-=Y.
C;
return *
this; }
36 {
return {
R*Y.
R-
C*Y.
C,
R*Y.
C+
C*Y.
R}; }
38 {
double N=1.0/Y.
norm();
return {(
R*Y.
R+
C*Y.
C)*N, (
C*Y.
R-
R*Y.
C)*N}; }
40 {
return {
R*T,
C*T}; }
42 {
R*=T;
C*=T;
return *
this; }
44 {
double r=
R*Y.
R-
C*Y.
C;
C=
R*Y.
C+
C*Y.
R;
R=r;
return *
this; }
49 static const double twopi = vnl_math::twopi;
51 static const double epsilonB = 2.e-03;
53 static const double final_eps = 1.e-10;
54 static const double stepinit = 1.e-02;
60 std::vector<vnl_vector<double>*> rr;
61 auto rp =
r_.begin(), ip =
i_.begin();
62 for (; rp !=
r_.end() && ip !=
i_.end(); ++rp, ++ip)
63 if ((*ip)->squared_magnitude() < tol)
75 static void inptbr(std::vector<vnl_rnpoly_solve_cmplx>& p, std::vector<vnl_rnpoly_solve_cmplx>& q)
101 p.resize(dim_); q.resize(dim_);
102 for (
unsigned int j=0; j<dim_; ++j) {
int jj=j%10; p[j]=pp[jj]; q[j]=qq[jj]; }
110 if (n>0)
while (n--) x *= y;
111 else while (n++) x /= y;
116 static void initr(std::vector<unsigned int>
const& ideg,
117 std::vector<vnl_rnpoly_solve_cmplx>
const& p,
118 std::vector<vnl_rnpoly_solve_cmplx>
const& q,
119 std::vector<vnl_rnpoly_solve_cmplx>& r,
120 std::vector<vnl_rnpoly_solve_cmplx>& pdg,
121 std::vector<vnl_rnpoly_solve_cmplx>& qdg)
123 assert(ideg.size()==dim_);
124 assert(p.size()==dim_);
125 assert(q.size()==dim_);
126 pdg.resize(dim_); qdg.resize(dim_); r.resize(dim_);
127 for (
unsigned int j=0;j<dim_;j++)
129 pdg[j] = powr(ideg[j],p[j]);
130 qdg[j] = powr(ideg[j],q[j]);
138 static inline int degree(
int index)
140 return (index<0) ? 0 : (index % max_deg_) + 1;
147 static void ffunr(std::vector<double>
const& coeff,
148 std::vector<int>
const& polyn,
149 std::vector<unsigned int>
const& terms,
150 std::vector<vnl_rnpoly_solve_cmplx>
const& x,
151 std::vector<vnl_rnpoly_solve_cmplx>& pows,
152 std::vector<vnl_rnpoly_solve_cmplx>& f,
153 std::vector<vnl_rnpoly_solve_cmplx>& df)
155 assert(terms.size()==dim_);
156 assert(x.size()==dim_);
158 pows.resize(max_deg_*dim_);
159 for (
unsigned int i=0;i<dim_;i++)
161 int index = max_deg_*i;
163 for (
unsigned int j=1;j<max_deg_;++j,++index)
164 pows[index+1]= pows[index] * x[i];
168 for (
unsigned int i=0; i<dim_; ++i)
171 for (
unsigned int j=0;j<dim_;j++)
175 for (
unsigned int i=0; i<dim_; ++i)
176 for (
unsigned int j=0; j<terms[i]; ++j)
179 for (
unsigned int k=0; k<dim_; ++k)
181 int index=polyn[i*dim_*max_nterms_+j*dim_+k];
185 f[i] += tmp * coeff[i*max_nterms_+j];
189 for (
int i=dim_-1;i>=0;i--)
190 for (
int l=dim_-1;l>=0;l--)
193 for (
int j=terms[i]-1;j>=0;j--)
194 if (polyn[i*dim_*max_nterms_+j*dim_+l]>=0)
197 for (
int k=dim_-1;k>=0;k--)
199 int index=polyn[i*dim_*max_nterms_+j*dim_+k];
204 int deg = degree(index);
206 tmp *= pows[index-1];
213 df_il += tmp * coeff[i*max_nterms_+j];
223 static void gfunr(std::vector<unsigned int>
const& ideg,
224 std::vector<vnl_rnpoly_solve_cmplx>
const& pdg,
225 std::vector<vnl_rnpoly_solve_cmplx>
const& qdg,
226 std::vector<vnl_rnpoly_solve_cmplx>
const& pows,
227 std::vector<vnl_rnpoly_solve_cmplx>& g,
228 std::vector<vnl_rnpoly_solve_cmplx>& dg)
230 assert(ideg.size()==dim_);
231 assert(g.size()==dim_);
232 assert(dg.size()==dim_);
233 std::vector<vnl_rnpoly_solve_cmplx> pxdgm1(dim_), pxdg(dim_);
235 for (
unsigned int j=0; j<dim_; ++j)
241 tmp = pows[j*max_deg_+ideg[j]-2];
243 pxdgm1[j] = pdg[j] * tmp;
246 for (
unsigned int j=0; j<dim_; ++j)
248 int index = j*max_deg_+ideg[j]-1;
249 pxdg[j] = pdg[j] * pows[index];
252 for (
unsigned int j=0; j<dim_; ++j)
254 g[j] = pxdg[j] - qdg[j];
255 dg[j] = pxdgm1[j] * ideg[j];
263 static void hfunr(std::vector<unsigned int>
const& ideg,
264 std::vector<vnl_rnpoly_solve_cmplx>
const& pdg,
265 std::vector<vnl_rnpoly_solve_cmplx>
const& qdg,
267 std::vector<vnl_rnpoly_solve_cmplx>
const& x,
268 std::vector<vnl_rnpoly_solve_cmplx>& h,
269 std::vector<vnl_rnpoly_solve_cmplx>& dhx,
270 std::vector<vnl_rnpoly_solve_cmplx>& dht,
271 std::vector<int>
const& polyn,
272 std::vector<double>
const& coeff,
273 std::vector<unsigned int>
const& terms)
275 assert(ideg.size()==dim_);
276 assert(terms.size()==dim_);
277 assert(x.size()==dim_);
278 assert(h.size()==dim_);
279 assert(dht.size()==dim_);
280 assert(dhx.size()==dim_*dim_);
281 std::vector<vnl_rnpoly_solve_cmplx> df(dim_*dim_),dg(dim_),f(dim_),g(dim_);
282 std::vector<vnl_rnpoly_solve_cmplx> pows;
284 ffunr(coeff,polyn,terms,x,pows,f,df);
285 gfunr(ideg,pdg,qdg,pows,g,dg);
286 assert(f.size()==dim_);
287 assert(g.size()==dim_);
288 assert(dg.size()==dim_);
289 assert(df.size()==dim_*dim_);
291 double onemt=1.0 - t;
292 for (
unsigned int j=0; j<dim_; ++j)
294 for (
unsigned int i=0; i<dim_; ++i)
295 dhx[j*dim_+i] = df[j*dim_+i] * t;
297 dhx[j*dim_+j] += dg[j]*onemt;
298 dht[j] = f[j] - g[j];
299 h[j] = f[j] * t + g[j] * onemt;
306 static int ludcmp(std::vector<vnl_rnpoly_solve_cmplx>& a, std::vector<int>& indx)
308 std::vector<double> vv(dim_);
311 for (
unsigned int i=0; i<dim_; ++i)
314 for (
unsigned int j=0; j<dim_; ++j)
316 double temp = a[i*dim_+j].norm();
317 if (temp > big) big = temp;
319 if (big == 0.0)
return 1;
320 vv[i]=1.0/std::sqrt(big);
324 for (
unsigned int j=0; j<dim_; ++j)
326 for (
unsigned int i=0; i<j; ++i)
327 for (
unsigned int k=0; k<i; ++k)
328 a[i*dim_+j] -= a[i*dim_+k] * a[k*dim_+j];
332 unsigned int imax = 0;
334 for (
unsigned int i=j; i<dim_; ++i)
336 for (
unsigned int k=0; k<j; ++k)
337 a[i*dim_+j] -= a[i*dim_+k] * a[k*dim_+j];
340 double rdum = vv[i]*a[i*dim_+j].norm();
341 if (rdum >= big) { big = rdum; imax = i; }
348 for (
unsigned int k=0; k<dim_; ++k)
351 a[imax*dim_+k] = a[j*dim_+k]; a[j*dim_+k] = dum;
360 if (ajj.
norm() == 0.0)
369 for (
unsigned int i=j+1; i<dim_; ++i)
378 static void lubksb(std::vector<vnl_rnpoly_solve_cmplx>
const& a,
379 std::vector<int>
const& indx,
380 std::vector<vnl_rnpoly_solve_cmplx>
const& bb,
381 std::vector<vnl_rnpoly_solve_cmplx>& b)
384 for (
unsigned int k=0; k<dim_; ++k)
387 for (
unsigned int i=0; i<dim_; ++i)
394 for (
unsigned int j=ii;j<i;++j)
395 sum -= a[i*dim_+j] * b[j];
399 if (sum.
norm() > 0) ii = i;
405 for (
int i=dim_-1;i>=0;i--)
407 for (
unsigned int j=i+1; j<dim_; ++j)
408 b[i] -= a[i*dim_+j] * b[j];
417 static int linnr(std::vector<vnl_rnpoly_solve_cmplx>& dhx,
418 std::vector<vnl_rnpoly_solve_cmplx>
const& rhs,
419 std::vector<vnl_rnpoly_solve_cmplx>& resid)
421 std::vector<int> irow(dim_);
422 if (ludcmp(dhx,irow)==1)
return 1;
423 lubksb(dhx,irow,rhs,resid);
430 static double xnorm(std::vector<vnl_rnpoly_solve_cmplx>
const&
v)
432 assert(
v.size()==dim_);
434 for (
unsigned int j=0; j<dim_; ++j)
435 txnorm += std::fabs(
v[j].R) + std::fabs(
v[j].C);
441 static void predict(std::vector<unsigned int>
const& ideg,
442 std::vector<vnl_rnpoly_solve_cmplx>
const& pdg,
443 std::vector<vnl_rnpoly_solve_cmplx>
const& qdg,
444 double step,
double& t,
445 std::vector<vnl_rnpoly_solve_cmplx>& x,
446 std::vector<int>
const& polyn,
447 std::vector<double>
const& coeff,
448 std::vector<unsigned int>
const& terms)
450 assert(ideg.size()==dim_);
451 assert(terms.size()==dim_);
452 assert(x.size()==dim_);
458 std::vector<vnl_rnpoly_solve_cmplx> dht(dim_),dhx(dim_*dim_),dz(dim_),h(dim_),rhs(dim_);
460 hfunr(ideg,pdg,qdg,t,x,h,dhx,dht,polyn,coeff,terms);
462 for (
unsigned int j=0; j<dim_; ++j)
466 if (linnr(dhx,rhs,dz) == 1)
return;
469 double factor = step/(1+xnorm(dz));
470 if (factor>maxdt) factor = maxdt;
473 if (t+factor>1) { tis1 =
false; factor = 1.0 - t; }
476 for (
unsigned int j=0; j<dim_; ++j)
477 x[j] += dz[j] * factor;
479 if (tis1) t += factor;
492 static int correct(std::vector<unsigned int>
const& ideg,
int loop,
double eps,
493 std::vector<vnl_rnpoly_solve_cmplx>
const& pdg,
494 std::vector<vnl_rnpoly_solve_cmplx>
const& qdg,
496 std::vector<vnl_rnpoly_solve_cmplx>& x,
497 std::vector<int>
const& polyn,
498 std::vector<double>
const& coeff,
499 std::vector<unsigned int>
const& terms)
501 double maxroot= 1000;
502 std::vector<vnl_rnpoly_solve_cmplx> dhx(dim_*dim_),dht(dim_),h(dim_),resid(dim_);
504 assert(ideg.size()==dim_);
505 assert(terms.size()==dim_);
506 assert(x.size()==dim_);
508 for (
int i=0;i<loop;i++)
510 hfunr(ideg,pdg,qdg,t,x,h,dhx,dht,polyn,coeff,terms);
513 if (linnr(dhx,h,resid)==1)
return 1;
515 for (
unsigned int j=0; j<dim_; ++j)
518 double xresid = xnorm(resid);
519 if (xresid < eps)
return 0;
520 if (xresid > maxroot)
return 3;
537 static int trace(std::vector<vnl_rnpoly_solve_cmplx>& x,
538 std::vector<unsigned int>
const& ideg,
539 std::vector<vnl_rnpoly_solve_cmplx>
const& pdg,
540 std::vector<vnl_rnpoly_solve_cmplx>
const& qdg,
541 std::vector<int>
const& polyn,
542 std::vector<double>
const& coeff,
543 std::vector<unsigned int>
const& terms)
545 assert(ideg.size()==dim_);
546 assert(terms.size()==dim_);
547 assert(x.size()==dim_);
557 double epsilonS=1.0e-3 * epsilonB;
558 double stepmin=1.0e-5 * stepinit;
559 double step=stepinit;
562 std::vector<vnl_rnpoly_solve_cmplx> oldx = x;
565 for (
int numstep=0;numstep<maxns;numstep++)
568 predict(ideg,pdg,qdg,step,t,x,polyn,coeff,terms);
574 if (eps != epsilonS) step = step/4.0;
580 std::cout <<
"t=" << t << std::endl;
586 std::cout <<
"path converged\n" << std::flush;
588 double factor = (1.0-oldt)/(t-oldt);
589 for (
unsigned int j=0; j<dim_; ++j)
590 x[j] = oldx[j] + (x[j]-oldx[j]) * factor;
592 int cflag=correct(ideg,10*maxit,final_eps,pdg,qdg,t,x, polyn, coeff,terms);
593 if ((cflag==0) ||(cflag==2))
601 int cflag=correct(ideg,maxit,eps,pdg,qdg,t,x,polyn, coeff,terms);
605 if ((++nadv)==maxit) { step *= 2; nadv=0; }
615 if (cflag==3)
return 3;
616 if (step<stepmin)
return 2;
631 static void strptr(std::vector<unsigned int>& icount,
632 std::vector<unsigned int>
const& ideg,
633 std::vector<vnl_rnpoly_solve_cmplx>
const& r,
634 std::vector<vnl_rnpoly_solve_cmplx>& x)
636 assert(ideg.size()==dim_);
637 assert(r.size()==dim_);
640 for (
unsigned int i=0; i<dim_; ++i)
641 if (icount[i] >= ideg[i]) icount[i] = 1;
642 else { icount[i]++;
break; }
644 for (
unsigned int j=0; j<dim_; ++j)
646 double angle = twopi / ideg[j] * icount[j];
652 static std::vector<std::vector<vnl_rnpoly_solve_cmplx> >
653 Perform_Distributed_Task(std::vector<unsigned int>
const& ideg,
654 std::vector<unsigned int>
const& terms,
655 std::vector<int>
const& polyn,
656 std::vector<double>
const& coeff)
658 assert(ideg.size()==dim_);
660 std::vector<std::vector<vnl_rnpoly_solve_cmplx> > sols;
661 std::vector<vnl_rnpoly_solve_cmplx> pdg, qdg, p, q, r, x;
662 std::vector<unsigned int> icount(dim_,1); icount[0]=0;
665 char const* FILENAM =
"/tmp/cont.results";
666 std::ofstream F(FILENAM);
669 std::cerr<<
"could not open "<<FILENAM<<
" for writing\nplease erase old file first\n";
673 std::cerr <<
"Writing to " << FILENAM <<
'\n';
677 initr(ideg,p,q,r,pdg,qdg);
681 for (
unsigned int j=0;j<dim_;j++) totdegree *= ideg[j];
686 while ((totdegree--) > 0)
689 strptr(icount,ideg,r,x);
692 solflag = 1 == trace(x,ideg,pdg,qdg,polyn,coeff,terms);
697 for (
unsigned int i=0; i<dim_; ++i)
698 F <<
'<' << x[dim_-i-1].R <<
' ' << x[dim_-i-1].C <<
'>';
705 if (solflag) std::cout <<
'.';
706 else std::cout <<
'*';
712 std::cout<< std::endl;
722 std::vector<unsigned int>& terms,
723 std::vector<int>& polyn,
724 std::vector<double>& coeff)
729 ideg.resize(dim_); terms.resize(dim_);
733 for (
unsigned int i=0;i<dim_;i++)
735 ideg[i] =
ps_[i]->ideg_;
736 terms[i] =
ps_[i]->nterms_;
737 if (ideg[i] > max_deg_)
739 if (terms[i] > max_nterms_)
740 max_nterms_ = terms[i];
742 coeff.resize(dim_*max_nterms_);
743 polyn.resize(dim_*max_nterms_*dim_);
744 for (
unsigned int i=0;i<dim_;i++)
746 for (
unsigned int k=0;k<terms[i];k++)
748 coeff[i*max_nterms_+k] =
ps_[i]->coeffs_(k);
749 for (
unsigned int j=0;j<dim_;j++)
751 int deg =
ps_[i]->polyn_(k,j);
752 polyn[i*dim_*max_nterms_+k*dim_+j] = deg ? int(j*max_deg_)+deg-1 : -1;
761 while (
r_.size() > 0) {
delete r_.back();
r_.pop_back(); }
762 while (
i_.size() > 0) {
delete i_.back();
i_.pop_back(); }
767 std::vector<unsigned int> ideg, terms;
768 std::vector<int> polyn;
769 std::vector<double> coeff;
772 assert(ideg.size()==dim_);
773 assert(terms.size()==dim_);
774 assert(polyn.size()==dim_*max_nterms_*dim_);
775 assert(coeff.size()==dim_*max_nterms_);
778 for (
unsigned int j=0; j<dim_; ++j) totdegree *= ideg[j];
780 std::vector<std::vector<vnl_rnpoly_solve_cmplx> > ans = Perform_Distributed_Task(ideg,terms,polyn,coeff);
785 std::cout <<
"Total degree: " << totdegree << std::endl
786 <<
"# solutions : " << ans.
size() << std::endl;
788 for (
auto & an : ans)
790 assert(an.size()==dim_);
793 for (
unsigned int j=0; j<dim_; ++j)
796 std::cout << ans[i][j].R <<
" + j " << ans[i][j].C << std::endl;
798 (*rp)[j]=an[j].R; (*ip)[j]=an[j].C;
801 std::cout<< std::endl;
bool compute()
Compute roots using continuation algorithm.
std::vector< vnl_real_npolynomial * > ps_
std::vector< vnl_vector< double > * > i_
vnl_rnpoly_solve_cmplx operator/(vnl_rnpoly_solve_cmplx const &Y) const
size_t size() const
Return the length, number of elements, dimension of this vector.
vnl_rnpoly_solve_cmplx(double a=0, double b=0)
vnl_rnpoly_solve_cmplx & operator/=(vnl_rnpoly_solve_cmplx const &Y)
Namespace with standard math functions.
void Read_Input(std::vector< unsigned int > &ideg, std::vector< unsigned int > &terms, std::vector< int > &polyn, std::vector< double > &coeff)
This will read the input polynomials from a data file.
This is a local implementation of a minimal "complex number" class, for internal use only.
vnl_rnpoly_solve_cmplx operator *(vnl_rnpoly_solve_cmplx const &Y) const
std::vector< vnl_vector< double > * > realroots(double tol=1e-12)
Return real roots only.
vnl_rnpoly_solve_cmplx operator+(vnl_rnpoly_solve_cmplx const &Y) const
vnl_rnpoly_solve_cmplx & operator-=(vnl_rnpoly_solve_cmplx const &Y)
vnl_rnpoly_solve_cmplx & operator *=(double T)
Solves for roots of system of real polynomials.
T angle(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
std::vector< vnl_vector< double > * > r_
vnl_rnpoly_solve_cmplx operator-() const
vnl_rnpoly_solve_cmplx operator-(vnl_rnpoly_solve_cmplx const &Y) const
vnl_rnpoly_solve_cmplx & operator+=(vnl_rnpoly_solve_cmplx const &Y)