00001
00002
00003
00004
00005
00006
00007 #ifndef synaps_sweep2d_topology_H
00008 #define synaps_sweep2d_topology_H
00009
00010 #include <vector>
00011 #include <map>
00012 #include <synaps/init.h>
00013 #include <synaps/base/Seq.h>
00014 #include <synaps/arithm/gmp.h>
00015 #include <synaps/linalg/VectDse.h>
00016 #include <synaps/linalg/MatrDse.h>
00017 #include <synaps/upol/UPolDse.h>
00018 #include <synaps/upol/SturmSeq.h>
00019 #include <synaps/upol/square_free.h>
00020 #include <synaps/mpol/MPol.h>
00021 #include <synaps/mpol/let.h>
00022 #include <synaps/mpol/subs.h>
00023 #include <synaps/usolve/Aberth.h>
00024 #include <synaps/topology/point.h>
00025 #include <synaps/topology/point_graph.h>
00026
00027
00028
00029 __BEGIN_NAMESPACE_SYNAPS
00030
00031 namespace projection
00032 {
00038 template<class C>
00039 struct list_X_Y
00040 {
00041 Seq<C> X;
00042 Seq<Seq<C> > Y;
00043 Seq<int> I;
00044 void clear()
00045 {
00046 X.resize(0);
00047 Y.resize(0);
00048 I.resize(0);
00049 }
00050
00051 };
00052
00053 template<class C>
00054 void print(const list_X_Y<C>& L)
00055 {
00056 for(unsigned i=0;i<L.X.size();i++)
00057 std::cout<<L.X[i]<<" ["<<L.Y[i]<<"] "<<L.I[i]<<std::endl;
00058 }
00059
00060 template<class C, class POL>
00061 POL easyquot (const POL& p, C beta, unsigned int n=1)
00062 {
00063
00064 POL r(p), l(C(1),1);
00065 l-= POL(beta,0);
00066 for(unsigned i=0;i<n;++i)
00067 r/=l;
00068
00069 return r;
00070 }
00071
00072 template<class C>
00073 unsigned insert(Seq<C>& L, const C& x)
00074 {
00075 unsigned i=0;
00076 typename Seq<C>::iterator it=L.begin();
00077 while(it !=L.end() && x> (*it) )
00078 {it++; i++;}
00079 L.rep().insert(it,x);
00080
00081 return i;
00082 }
00083
00084 template<class C>
00085 unsigned insert(list_X_Y<C>& L, const C& x, const Seq<C>& LY, int mu)
00086 {
00087 if(LY.size())
00088 {
00089
00090 unsigned i=0;
00091 typename Seq<C>::iterator itX=L.X.begin();
00092 typename Seq<Seq<C> >::iterator itY=L.Y.begin();
00093 typename Seq<int>::iterator itI=L.I.begin();
00094 while(itX !=L.X.end() && x> (*itX) )
00095 {itX++; itY++; itI++, i++;}
00096 L.X.rep().insert(itX,x);
00097 L.Y.rep().insert(itY,LY);
00098 L.I.rep().insert(itI,mu);
00099
00100 }
00101 }
00102
00103 template<class C,class O, class R>
00104 UPolDse<double> eval_to_double(const MPol<C,O,R> & p, double x)
00105 {
00106 UPolDse<double> tmp(degree(p,1)+1, AsSize());
00107 VECTOR::init(tmp,0);
00108 double c;
00109 for(typename MPol<C,O,R>::const_iterator it=p.begin(); it !=p.end();it++)
00110 {
00111 unsigned d0=(*it)[0], d1=(*it)[1];
00112 c =let::convert(it->coeff(),type::As<double>());
00113 for(unsigned i=0;i<d0;i++) c*=x;
00114 tmp[d1]+=c;
00115 }
00116 return tmp;
00117 }
00118
00119 template<class C>
00120 UPolDse<double> convert_to_double(const UPolDse<C> & P)
00121 {
00122 UPolDse<double> tmp(degree(P)+1, AsSize());
00123 for( unsigned k=0; k< tmp.size();++k)
00124 let::assign(tmp[k],P[k]);
00125 return tmp;
00126 }
00127
00128
00129 template<class POL>
00130 POL change_x_minus_y(const POL& p)
00131 {
00132 return subs(0,POL("x0+x1"),p);
00133 }
00134
00135
00136 template<class GRAPH>
00137 void change_x_plus_y(GRAPH& g, int k)
00138 {
00139 if(k!=0)
00140 for(unsigned i=0;i< rep(g.Vertices).size(); i++)
00141 {
00142 rep(g.Vertices)[i][0]-=rep(g.Vertices)[i][1]*k;
00143 }
00144 }
00145
00146 template<class GRAPH>
00147 void swap_x_y(GRAPH& g)
00148 {
00149 for(unsigned i=0;i< rep(g.Vertices).size(); i++)
00150 {
00151 std::swap(rep(g.Vertices)[i][0],rep(g.Vertices)[i][1]);
00152 }
00153 }
00154
00155
00156 }
00157
00158 template<class O, class SLV=SlvAberth<RR>, class X=double>
00159 struct TopSweep2d
00160 {
00161 typedef O solution_t;
00162 X eps;
00163 unsigned nbpt;
00164 TopSweep2d():nbpt(1),eps(1.e-4) {}
00165 TopSweep2d(const X& e):nbpt(1),eps(e) {}
00166 TopSweep2d(int n):nbpt(n),eps(1.e-4) {}
00167 TopSweep2d(const TopSweep2d & mth):nbpt(mth.nbpt),eps(mth.eps) {}
00168
00169 typedef topology::point<double> point_t;
00170 typedef MatrDse<double> m_solution_t;
00171 typedef Seq<VectDse<double> > b_solution_t;
00172 typedef MPol<QQ> equation_t;
00173
00174 typedef Seq<RR> u_solution_t;
00175
00176 template<class POL>
00177 u_solution_t u_solve(const POL &p)
00178 {
00179 return solve(p,SLV());
00180 }
00181
00182
00183 template<class POL, class C>
00184 bool IsGeneric1(const POL& p, const C& alpha, const C& beta)
00185 {
00186 std::vector<C> x(2); x[0]=alpha;x[1]=beta;
00187 C v= MPOLDST::eval<C>(p,x);
00188 return (std::abs(v)< this->eps);
00189 }
00190
00191
00192 template<class POL, class C>
00193 bool IsGeneric2(const POL& p, const C& alpha, const C& beta, int k)
00194 {
00195 return true;
00196 }
00197
00198
00199 template<class C, class POL>
00200 void add_regular_y(Seq<C>& S,const POL& p,const C& alpha)
00201 {
00202 UPolDse<C> pol= projection::eval_to_double(p,alpha);
00203 u_solution_t y_sol = this->u_solve(pol);
00204 C beta;
00205 for(unsigned j=0;j<y_sol.size();j++)
00206 {
00207 let::assign(beta,y_sol[j]);
00208 S.push_back(beta);
00209 }
00210 std::sort(S.begin(),S.end());
00211 }
00212
00215 template<class C, class POL>
00216 void add_regular_point(projection::list_X_Y<C> & L,
00217 const projection::list_X_Y<C> & L0,
00218 const POL& p,
00219 unsigned N=1)
00220 {
00221 typedef C coeff_t;
00222 using let::convert;
00223 if(L0.X.size() && N)
00224 {
00225 coeff_t alpha,beta, dx;
00226 Seq<double> SY;
00227
00228 alpha=L0.X[0]-1;
00229
00230 this->add_regular_y(SY,p,alpha);
00231 if(SY.size())
00232 {
00233 L.X.push_back(alpha);
00234 L.Y.push_back(SY);
00235 L.I.push_back(-1);
00236 }
00237
00238 dx=coeff_t(1)/(N+1);
00239 for(unsigned l=1;l<N+1; l++)
00240 {
00241 alpha+=dx;
00242 SY.resize(0);
00243 this->add_regular_y(SY,p,alpha);
00244 if(SY.size())
00245 {
00246 L.X.push_back(alpha);
00247 L.Y.push_back(SY);
00248 L.I.push_back(-1);
00249 }
00250 }
00251 for(unsigned i=0;i<L0.X.size();i++)
00252 {
00253 L.X.push_back(L0.X[i]);
00254 L.I.push_back(L0.I[i]);
00255 L.Y.push_back(L0.Y[i]);
00256 if(i<int(L0.X.size()-1))
00257 dx=(L0.X[i+1]-L0.X[i])/(N+1);
00258 else
00259 dx = C(1)/(N+1);
00260 alpha= L0.X[i]+dx;
00261 for(unsigned l=1;l<N+1; l++)
00262 {
00263 SY.resize(0);
00264 this->add_regular_y(SY,p,alpha);
00265 if(SY.size())
00266 {
00267 L.X.push_back(alpha);
00268 L.Y.push_back(SY);
00269 L.I.push_back(-1);
00270 }
00271 alpha+=dx;
00272 }
00273 }
00274 }
00275 else
00276 {
00277 C alpha=-1;
00278 Seq<C> SY;
00279 L.X.push_back(alpha);
00280 L.I.push_back(-1);
00281 this->add_regular_y(SY,p,alpha);
00282 L.Y.push_back(SY);
00283
00284 alpha=1;
00285 L.X.push_back(alpha);
00286 L.I.push_back(-1);
00287 SY.resize(0);
00288 this->add_regular_y(SY,p,alpha);
00289 L.Y.push_back(SY);
00290 }
00291 }
00292
00293
00294
00295 template<class GAMMAS, class STURMSEQ>
00296 bool isgeneric( GAMMAS & Gammas, STURMSEQ & SH )
00297 {
00298 typedef typename GAMMAS::value_type upol_t;
00299 typedef typename STURMSEQ::value_type bpol_t;
00300
00301 for ( int i = 0; i < Gammas.size(); i ++ )
00302 {
00303 bpol_t SHi = SH[SH.size()-i-2];
00304 upol_t betadenum = SHi[i+1]*(i+1);
00305 upol_t betanum = -SHi[i];
00306 if ( betadenum != 0 )
00307 {
00308 Rational<upol_t> f(betanum,betadenum);
00309 Rational<upol_t> r = SHi(f);
00310 upol_t nm = numerator(r);
00311 if ( nm % Gammas[i] != 0 ) return false;
00312 for ( int k = 0; k < i; k++ )
00313 {
00314 SHi = diff(SHi);
00315 r = SHi(f);
00316 nm = numerator(r);
00317 if ( nm % Gammas[i] != 0 ) return false;
00318 };
00319 };
00320 };
00321 return true;
00322 };
00323
00324
00325
00326 template<class C, class POL>
00327 bool insert_char_points(projection::list_X_Y<C> & L,
00328 const POL & p1, const POL& p2,
00329 bool both=false)
00330 {
00331 typedef POL mpol_t;
00332 typedef ZZ coeff_t;
00333 typedef UPolDse<coeff_t> upol_t;
00334 typedef UPolDse<UPolDse<coeff_t> > bpol_t;
00335 typedef std::vector<upol_t> vector_t;
00336
00337 using let::assign;
00338 using let::convert;
00339
00340 bpol_t p; assign(p,p1,1);
00341 bpol_t q; assign(q,p2,1);
00342
00343 std::cout<<"p1: "<<p<<std::endl;
00344 std::cout<<"p2: "<<q<<std::endl;
00345 bpol_t::var_= "y";
00346 upol_t qq=p[degree(p)];
00347 if( degree(qq) !=0) return false;
00348 SturmSeq<upol_t> s(p,q,HABICHT());
00349
00350 vector_t r=CoeffStHa<vector_t>(s);
00351 upol_t disc=square_free(r[r.size()-1]);
00352
00353 vector_t Gammas;
00354 upol_t Fi=disc,Fin;
00355
00356 for (unsigned j=0; j<r.size()-1; ++j)
00357 {
00358 Fin= gcd(Fi,r[r.size()-j-2]);
00359 if(Fin !=0) Gammas.push_back(Fi/Fin);
00360 Fi=Fin;
00361 }
00362
00363 if ( ! isgeneric( Gammas, s ) ) return false;
00364
00365
00366
00367 Seq<Seq<C> > Xmu, Ycrit, Sol;
00368 Seq<int> NbXmu;
00369 Seq<C> solx, soly;
00370
00371 std::map<double,int> mu;
00372 for (unsigned j=0; j<Gammas.size(); ++j)
00373 {
00374 if (degree(Gammas[j])>=1)
00375 {
00376 UPolDse<coeff_t> tmp =Gammas[j];
00377 std::cout<<"Solving polynomial "<<tmp <<std::endl;
00378 u_solution_t SolX = u_solve(tmp);
00379 double r;
00380 for(unsigned k=0; k< SolX.size();++k)
00381 {
00382 assign(r,SolX[k]);
00383 mu[r]=(j+1);
00384 solx.push_back(r);
00385
00386 }
00387 }
00388 else
00389 {
00390 Seq<double> tmpEmpty; NbXmu.push_back(0);
00391 Xmu.push_back(tmpEmpty);
00392 Ycrit.push_back(tmpEmpty);
00393 }
00394 }
00395 sort(solx.begin(),solx.end());
00396
00397
00398
00399
00400 for (unsigned l=0; l<solx.size(); ++l)
00401 {
00402 Seq<double> Yreg;
00403 double alpha=solx[l], beta;
00404 L.X.push_back(alpha);
00405
00406 int m=mu[alpha];
00407 if(m !=0)
00408 {
00409
00410
00411 bpol_t tp = s[s.size()-m-1];
00412 beta = -projection::convert_to_double(tp[m-1])(alpha)/
00413 projection::convert_to_double(tp[m])(alpha)/(m);
00414
00415 unsigned l=m+1;
00416 if(both) l=m;
00417 UPolDse<double> tmp1 =
00418 projection::easyquot( projection::eval_to_double(p1,alpha),beta,l);
00419
00420 if (degree(tmp1)>0)
00421 {
00422 std::cout<<"Solving polynomial(1) "<<tmp1<<std::endl;
00423 u_solution_t y_sol = u_solve(tmp1);
00424
00425 for(unsigned k=0; k<y_sol.size();++k)
00426 Yreg.push_back(convert(y_sol[k],type::As<double>()));
00427 }
00428
00429 if(both)
00430 {
00431 std::cout<<"Solving polynomial(2) "<<tmp1<<std::endl;
00432 tmp1 = projection::easyquot(projection::eval_to_double(p2,alpha),
00433 beta,m);
00434 if (degree(tmp1)>0)
00435 {
00436 u_solution_t y_sol = u_solve(tmp1);
00437 for(unsigned k=0; k<y_sol.size();++k)
00438 Yreg.push_back(convert(y_sol[k],type::As<double>()));
00439 }
00440
00441 }
00442 sort(Yreg.begin(),Yreg.end());
00443 L.I.push_back(projection::insert(Yreg,beta));
00444 }
00445 else
00446 {
00447
00448 UPolDse<double> tmp1= projection::eval_to_double(p1,alpha);
00449
00450 u_solution_t y_sol = u_solve(tmp1);
00451
00452 for(unsigned k=0; k<y_sol.size();++k)
00453 Yreg.push_back(convert(y_sol[k],type::As<double>()));
00454
00455 if(both)
00456 {
00457 tmp1= projection::eval_to_double(p1,alpha);
00458
00459 y_sol = u_solve(tmp1);
00460
00461 for(unsigned k=0; k<y_sol.size();++k)
00462 Yreg.push_back(convert(y_sol[k],type::As<double>()));
00463 }
00464 sort(Yreg.begin(),Yreg.end());
00465
00466 L.I.push_back(-1);
00467 }
00468
00469 L.Y.push_back(Yreg);
00470
00471 }
00472 return true;
00473 }
00474
00475
00476 template<class GRAPH, class C>
00477 void connect(GRAPH & g, const projection::list_X_Y<C>& L)
00478 {
00479 int n0,n1,s0,s1;
00480 n0=g.Vertices.size();
00481
00482 topology::point<double> p(2);
00483 s0=L.Y[0].size();
00484
00485 p[0]=L.X[0];
00486 for (int j=0;j<s0;j++)
00487 {
00488 p[1]=L.Y[0][j];
00489 g.push_back(p);
00490 }
00491
00492
00493 for (unsigned i=1; i<L.X.size();i++)
00494 {
00495
00496 p[0]=L.X[i];
00497 n1=n0+s0;
00498 s1=L.Y[i].size();
00499 for (int j=0;j<s1;j++)
00500 {
00501
00502 p[1]=L.Y[i][j];
00503 g.push_back(p);
00504
00505 }
00506
00507
00508 int ku0,ku1,kd0,kd1;
00509 if (L.I[i-1]>-1)
00510 {
00511 ku0=L.I[i-1];
00512 kd0=ku0+1;
00513 }
00514 else
00515 {
00516 ku0=s0;
00517 kd0=0;
00518 }
00519 if (L.I[i]>-1)
00520 {
00521 ku1=L.I[i];
00522 kd1=ku1+1;
00523 }
00524 else
00525 {
00526 ku1=s1;
00527 kd1=0;
00528 }
00529
00530
00531 int k0,k1;
00532
00533 for (k0=0;k0<ku0 && k0<ku1;k0++)
00534 {
00535 g.insert(n0+k0,n1+k0);
00536 std::cout<<"ru> "<<n0+k0<<" - "<<n1+k0<<" "
00537 <<g.Vertices[n0+k0]<<" "
00538 <<g.Vertices[n1+k0]
00539 << std::endl;
00540 }
00541 for (k1=0;k1<s0-kd0 && k1<s1-kd1;++k1)
00542 {
00543 g.insert(n0+s0-k1-1,n1+s1-k1-1);
00544 std::cout<<"rd> "<<n0+s0-k1-1<<" - "<<n1+s1-k1-1<<" "
00545 <<g.Vertices[n0+s0-k1-1]<<" "
00546 <<g.Vertices[n1+s1-k1-1]
00547 << std::endl;
00548 }
00549
00550 for (int j0=k0;j0<s0-k1;j0++)
00551 {
00552 for (int j1=k0;j1<s1-k1;j1++)
00553 {
00554 g.insert(n0+j0,n1+j1);
00555
00556
00557
00558
00559 }
00560
00561 }
00562 n0=n1; s0=s1;
00563 }
00564 }
00565
00566 };
00567
00568 namespace topology
00569 {
00570 template<class C,class U>
00571 void assign(point_graph<C>& g,
00572 const MPol<U>& eq,
00573 TopSweep2d<C> mth)
00574 {
00575 typedef C coeff_t;
00576 typedef MPol<U> mpol_t;
00577
00578 MPol<QQ> p; let::assign(p,eq);
00579
00580 projection::list_X_Y<coeff_t> L,Lr;
00581
00582 int nvc=0, d= degree(p);
00583 bool sw=false;
00584 if(!mth.insert_char_points(L,p,diff(p,1)))
00585 {
00586 p = MPOLDST::swap(p,0,1);
00587 sw=true;
00588 L.clear();
00589 std::cout<<"Not generic "<<nvc<<std::endl;
00590 while (!mth.insert_char_points(L,p,diff(p,1)) && nvc < (d*(d-1)))
00591 {
00592 p=projection::change_x_minus_y(p);
00593 nvc++;
00594 L.clear();
00595 std::cout<<"Not generic "<<nvc<<std::endl;
00596 }
00597 }
00598
00599 print(L);
00600 mth.add_regular_point(Lr,L,p,mth.nbpt);
00601
00602 print(Lr);
00603 mth.connect(g,Lr);
00604
00605 std::cout<<nvc<<std::endl;
00606 if(nvc >0)
00607 projection::change_x_plus_y(g,-nvc);
00608 if(sw)
00609 projection::swap_x_y(g);
00610 std::cout<<g.Vertices.size()<<std::endl;
00611 }
00612
00613 template<class C,class U>
00614 void assign(point_graph<C>& g,
00615 const MPol<U>& P1,
00616 const MPol<U>& P2,
00617 TopSweep2d<C> mth)
00618 {
00619 typedef TopSweep2d<C> mth_t;
00620 typedef typename TopSweep2d<C>::u_solution_t u_solution_t;
00621
00622 MPol<QQ> p1; let::assign(p1,P1);
00623 MPol<QQ> p2; let::assign(p2,P2);
00624
00625 projection::list_X_Y<C> L1,L2,LI,LIr;
00626 mth.insert_char_points(L1,p1,diff(p1,1));
00627 mth.insert_char_points(L2,p2,diff(p2,1));
00628
00629 std::cout<<"====================================="<<std::endl;
00630 std::cout<<"C1"<<std::endl;
00631 print(L1);
00632 std::cout<<"====================================="<<std::endl;
00633 std::cout<<"C2"<<std::endl;
00634 print(L2);
00635
00636
00637 double alpha,beta;
00638 int mu;
00639 for(unsigned i=0; i< L2.X.size();i++)
00640 {
00641 alpha=L2.X[i];
00642 UPolDse<double> tmp1= projection::eval_to_double(p1,alpha);
00643
00644 u_solution_t y_sol = mth.u_solve(tmp1);
00645
00646 for(unsigned j=0;j<y_sol.size();j++)
00647 {
00648 let::assign(beta,y_sol[j]);
00649 mu=projection::insert(L2.Y[i],beta);
00650 if(mu<=L2.I[i]) L2.I[i]++;
00651
00652 }
00653 }
00654 for(unsigned i=0; i< L1.X.size();i++)
00655 {
00656 alpha=L1.X[i];
00657 UPolDse<double> tmp1= projection::eval_to_double(p2,alpha);
00658
00659 u_solution_t y_sol = mth.u_solve(tmp1);
00660
00661 for(unsigned j=0;j<y_sol.size();j++)
00662 {
00663 let::assign(beta,y_sol[j]);
00664 mu=projection::insert(L1.Y[i],beta);
00665 if(mu<=L1.I[i]) L1.I[i]++;
00666 }
00667 }
00668
00669 std::cout<<"====================================="<<std::endl;
00670 std::cout<<"C1"<<std::endl;
00671 print(L1);
00672 std::cout<<"====================================="<<std::endl;
00673 std::cout<<"C2"<<std::endl;
00674 print(L2);
00675 std::cout<<"====================================="<<std::endl;
00676 for(unsigned i=0; i< L2.X.size();i++)
00677 projection::insert(L1,L2.X[i],L2.Y[i],L2.I[i]);
00678 print(L1);
00679 std::cout<<"====================================="<<std::endl;
00680 mth.insert_char_points(LI,p1,p2,true);
00681 print(LI);
00682 std::cout<<">>==================================="<<std::endl;
00683 for(unsigned i=0; i< LI.X.size();i++)
00684 {
00685 projection::insert(L1,LI.X[i],LI.Y[i],LI.I[i]);
00686 }
00687
00688 for(int i=0;i<L1.X.size()-1;i++)
00689 {
00690 if(L1.I[i]>=0 && L1.I[i+1]>=0)
00691 {
00692 alpha= (L1.X[i]+L1.X[i+1])/2;
00693 Seq<double> ly;
00694 UPolDse<double> tmp1= projection::eval_to_double(p1,alpha);
00695 u_solution_t y_sol = mth.u_solve(tmp1);
00696
00697 for(unsigned j=0; j<y_sol.size();j++)
00698 {
00699 let::assign(beta,y_sol[j]);
00700 ly.push_back(beta);
00701 }
00702 tmp1= projection::eval_to_double(p2,alpha);
00703 y_sol = mth.u_solve(tmp1);
00704 for(unsigned j=0; j<y_sol.size();j++)
00705 {
00706 let::assign(beta,y_sol[j]);
00707 ly.push_back(beta);
00708 }
00709 sort(ly.begin(),ly.end());
00710 projection::insert(LIr,alpha,ly,-1);
00711 }
00712 }
00713 std::cout<<"<<==================================="<<std::endl;
00714 for(unsigned i=0; i< LIr.X.size();i++)
00715 {
00716 projection::insert(L1,LIr.X[i],LIr.Y[i],LIr.I[i]);
00717 }
00718 std::cout<<"<<==================================="<<std::endl;
00719 print(L1);
00720 std::cout<<">>==================================="<<std::endl;
00721 mth.connect(g,L1);
00722 }
00723 }
00724
00725
00726 __END_NAMESPACE_SYNAPS
00727
00728 #endif //synaps_sweep2d_topology_H