polygon.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "polygon.hpp"
  2. Coefficients Polygon::coefficients;
  3. Polygon::Polygon(string str){
  4. Vertex v(0,0);
  5. indices.insert({v,0});
  6. vertices.push_back(v);
  7. length=0;
  8. size_t i=0;
  9. size_t l=str.size();
  10. if(l==0) return;
  11. char c=str[0];
  12. while(i<l){
  13. char s=c;
  14. int64 xs=0;
  15. int64 ys=0;
  16. switch(s){
  17. case 'l':
  18. xs=-1;
  19. break;
  20. case 'r':
  21. xs=1;
  22. break;
  23. case 'u':
  24. ys=1;
  25. break;
  26. case 'd':
  27. ys=-1;
  28. break;
  29. default:
  30. Error::string_error("Invalid step",str,i);
  31. break;
  32. };
  33. size_t j=++i;
  34. size_t n=0;
  35. if(i<l){
  36. c=str[i];
  37. while(i<l and '0'<=c and c<='9'){
  38. n=n*10+c-'0';
  39. if(++i==l) break;
  40. c=str[i];
  41. }
  42. }
  43. if(i==j) n=1; // No digits after step s
  44. for(size_t k=0;k<n;++k){
  45. v.x+=xs;
  46. v.y+=ys;
  47. ++length;
  48. auto res=indices.insert({v,length});
  49. if(!res.second and (i<l or k<n-1)) Error::string_error("Not self avoiding",str,j-1);
  50. if(res.second) vertices.push_back(v);
  51. }
  52. }
  53. if(v.x!=0 or v.y!=0) Error::error("Not a polygon");
  54. compute_B();
  55. compute_fp();
  56. }
  57. void Polygon::add_vertex(const int32& x,const int32& y){
  58. Vertex w(x,y);
  59. if(indices.find(w)==indices.end()){
  60. indices.insert({w,vertices.size()});
  61. vertices.push_back(w);
  62. }
  63. }
  64. void
  65. Polygon::add_neighbours(const int32& x,const int32& y){
  66. add_vertex(x,y+1);
  67. add_vertex(x,y-1);
  68. add_vertex(x-1,y);
  69. add_vertex(x+1,y);
  70. }
  71. void
  72. Polygon::compute_B(){
  73. for(size_t i=0;i<length;++i){
  74. int32 x=vertices[i].x;
  75. int32 y=vertices[i].y;
  76. add_neighbours(x,y);
  77. }
  78. B.init(vertices.size());
  79. B.clear();
  80. for(size_t i=0;i<length;++i){
  81. Vertex& v=vertices[i];
  82. size_t r=indices[Vertex(v.x+1,v.y)];
  83. size_t l=indices[Vertex(v.x-1,v.y)];
  84. size_t u=indices[Vertex(v.x,v.y+1)];
  85. size_t d=indices[Vertex(v.x,v.y-1)];
  86. B.set(i,r);
  87. B.set(r,i);
  88. B.set(i,l);
  89. B.set(l,i);
  90. B.set(i,u);
  91. B.set(u,i);
  92. B.set(i,d);
  93. B.set(d,i);
  94. }
  95. }
  96. void
  97. Polygon::compute_C(Matrix& C){
  98. C.init(vertices.size());
  99. size_t n=vertices.size();
  100. for(size_t i=0;i<n;++i){
  101. for(size_t j=0;j<n;++j){
  102. Vertex& vi=vertices[i];
  103. Vertex& vj=vertices[j];
  104. double dx=abs(vi.x-vj.x);
  105. double dy=abs(vi.y-vj.y);
  106. C.set(i,j,coefficients.get(dx,dy));
  107. }
  108. }
  109. }
  110. void
  111. Polygon::compute_M(Matrix& M,const Matrix& C){
  112. //M=[I+1/4*C*B|1]=[I+1/4*C*tB|1]
  113. size_t n=vertices.size();
  114. mpfr_t temp;
  115. mpfr_init2(temp,prec);
  116. M.init(n,n+1);
  117. M.clear();
  118. for(size_t i=0;i<n;++i){
  119. for(size_t j=0;j<n;++j){
  120. mpfr_set_zero(temp,0);
  121. for(size_t k=0;k<n;++k){
  122. if(B.get(k,j)!=0){
  123. mpfr_add(temp,temp,C.get(i,k),MPFR_RNDN);
  124. }
  125. }
  126. mpfr_div_ui(temp,temp,4,MPFR_RNDN);
  127. M.set(i,j,temp);
  128. }
  129. mpfr_add_ui(M.get(i,i),M.get(i,i),1,MPFR_RNDN);
  130. mpfr_set_ui(M.get(i,n),1,MPFR_RNDN);
  131. }
  132. }
  133. void
  134. Polygon::compute_fp(){
  135. Matrix C,M;
  136. compute_C(C);
  137. compute_M(M,C);
  138. size_t n=vertices.size();
  139. mpfr_t det,temp;
  140. mpfr_init2(det,prec);
  141. mpfr_init2(fp,prec);
  142. mpfr_init2(temp,prec);
  143. mpfr_set_zero(fp,0);
  144. M.Gauss(det);
  145. mpfr_printf("Det = %Re\n",det);
  146. for(size_t i=0;i<n;++i){
  147. mpfr_set_ui(temp,B.get_diag_square_sym(i),MPFR_RNDN);
  148. mpfr_fma(fp,temp,M.get(i,n),fp,MPFR_RNDN);
  149. }
  150. mpfr_mul(fp,fp,det,MPFR_RNDN);
  151. mpfr_div_ui(fp,fp,4,MPFR_RNDN);
  152. mpfr_clear(det);
  153. mpfr_clear(temp);
  154. }