Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

cn94.cpp

Go to the documentation of this file.
00001 #include <limits>
00002 #include <iostream>
00003 #include <iterator>
00004 #include <vector>
00005 #include "cn94.hpp"
00006 
00007 using namespace Arak;
00008 using namespace Arak::Geometry;
00009 
00010 const char* CN94Proposal::moveNames[numMoveTypes] = {
00011   "interior triangle birth",
00012   "interior triangle death",
00013   "recolor quadrilateral",
00014   "move interior vertex",
00015   "move vertex along boundary",
00016   "move vertex past corner",
00017   "interior vertex birth",
00018   "interior vertex death",
00019   "boundary triangle birth",
00020   "boundary triangle death",
00021   "corner cut birth",
00022   "corner cut death",
00023   "invalid move"
00024 };
00025 
00026 Point CN94Proposal::sampleInCastingBox(const Point& p,
00027                Arak::Util::Random& random) const {
00028   double x = CGAL::to_double(p.x());
00029   double y = CGAL::to_double(p.y());
00030   return Point(random.uniform(x - castingBoxRadius,
00031             x + castingBoxRadius),
00032          random.uniform(y - castingBoxRadius,
00033             y + castingBoxRadius));
00034 }
00035 
00036 bool CN94Proposal::inCastingBox(const Point& p, const Point& q) const {
00037   return ((fabs(CGAL::to_double(p.x() - q.x())) <= castingBoxRadius) &&
00038     (fabs(CGAL::to_double(p.y() - q.y())) <= castingBoxRadius));
00039 }
00040 
00042 
00043 void CN94Proposal::InteriorTriangleBirth::reset(const Point& u, const Point& v, const Point& w) {
00044   this->u = u;
00045   this->v = v;
00046   this->w = w;
00047   vh = Coloring::VertexHandle();
00048 }
00049 
00050 void CN94Proposal::InteriorTriangleBirth::execute(Coloring& c) {
00051   vh = c.newInteriorTriangle(u, v, w, Coloring::DO_WITHOUT_TEST_TAG());
00052   assert(vh.valid());
00053 }
00054   
00055 void CN94Proposal::InteriorTriangleBirth::undo(Coloring& c) {
00056   assert(c.deleteIntTriangle(vh, Coloring::DO_WITHOUT_TEST_TAG()));
00057 }
00058   
00060 
00061 void CN94Proposal::InteriorTriangleDeath::reset(Coloring::VertexHandle vertex,
00062             bool isShort) {
00063   vh = vertex;
00064   this->isShort = isShort;
00065   u = vertex->point();
00066   const Coloring::VertexHandle intVertex = vertex->getNextVertex();
00067   const Coloring::VertexHandle bdVertex = intVertex->getNextVertex();
00068   v = bdVertex->point();
00069   w = intVertex->point();
00070 }
00071 
00072 void CN94Proposal::InteriorTriangleDeath::execute(Coloring& c) {
00073   assert(vh.valid());
00074   assert(c.deleteIntTriangle(vh, Coloring::DO_WITHOUT_TEST_TAG()));
00075 }
00076   
00077 void CN94Proposal::InteriorTriangleDeath::undo(Coloring& c) {
00078   assert(!vh.valid());
00079   vh = c.newInteriorTriangle(u, v, w, Coloring::DO_WITHOUT_TEST_TAG());
00080   assert(vh.valid());
00081 }
00082   
00084 
00085 void CN94Proposal::Recolor::reset(Coloring::IntEdgeHandle edge1, 
00086           Coloring::IntEdgeHandle edge2,
00087           bool joinSourceToSource,
00088           bool convex) {
00089   this->edge1 = edge1;
00090   this->edge2 = edge2;
00091   this->joinSourceToSource = joinSourceToSource;
00092   this->convex = convex;
00093 }
00094 
00095 void CN94Proposal::Recolor::execute(Coloring& c) {
00096   Coloring::VertexHandle a = edge1->getPrevVertex();
00097   Coloring::VertexHandle b = edge1->getNextVertex();
00098   assert(c.recolorQuadrilateral(edge1, edge2, 
00099         joinSourceToSource, Coloring::DO_WITHOUT_TEST_TAG()));
00100   // Update joinSourceToSource for a potential undo.
00101   joinSourceToSource = 
00102     (((a == edge1->getPrevVertex()) && (b == edge2->getPrevVertex())) ||
00103      ((b == edge1->getPrevVertex()) && (a == edge2->getPrevVertex())) ||
00104      ((a == edge1->getNextVertex()) && (b == edge2->getNextVertex())) ||
00105      ((b == edge1->getNextVertex()) && (a == edge2->getNextVertex())));
00106 }
00107 
00108 void CN94Proposal::Recolor::undo(Coloring& c) {
00109   execute(c);
00110 }
00111 
00113 
00114 void CN94Proposal::MoveBdVertexPastCorner::reset(Coloring::BdEdgeHandle edge, 
00115              const Point& point) { 
00116   this->edge = edge;
00117   this->oldLoc = (edge->getPrevVertex()->type() == Coloring::Vertex::CORNER) ?
00118     edge->getNextVertex()->point() : edge->getPrevVertex()->point();
00119   this->newLoc = point;
00120 }
00121 
00122 void CN94Proposal::MoveBdVertexPastCorner::execute(Coloring& c) {  
00123   assert(c.moveBdVertexPastCorner(edge, newLoc, Coloring::DO_WITHOUT_TEST_TAG()));
00124 }
00125 
00126 void CN94Proposal::MoveBdVertexPastCorner::undo(Coloring& c) { 
00127   assert(edge.valid());
00128   assert(c.moveBdVertexPastCorner(edge, oldLoc, Coloring::DO_WITHOUT_TEST_TAG()));
00129 }
00130 
00132 
00133 void CN94Proposal::InteriorVertexBirth::reset(Coloring::IntEdgeHandle edge, 
00134                 const Point& point) {
00135   this->prevVertex = edge->getPrevVertex();
00136   this->nextVertex = edge->getNextVertex();
00137   this->point = point;
00138 }
00139 
00140 void CN94Proposal::InteriorVertexBirth::execute(Coloring& c) {
00141   Coloring::IntEdgeHandle edge = prevVertex->getNextIntEdge();
00142   assert(c.splitEdge(edge, point, Coloring::DO_WITHOUT_TEST_TAG()));
00143 }
00144 
00145 void CN94Proposal::InteriorVertexBirth::undo(Coloring& c) {
00146   Coloring::VertexHandle newVertex = prevVertex->getNextVertex();
00147   assert(c.deleteVertex(newVertex, Coloring::DO_WITHOUT_TEST_TAG()));
00148 }
00149 
00151 
00152 void CN94Proposal::InteriorVertexDeath::reset(Coloring::VertexHandle vertex) {
00153   this->prevVertex = vertex->getPrevVertex();
00154   this->point = vertex->point();
00155   Coloring::VertexHandle nextVertex = vertex->getNextVertex();
00156   newEdgeLength = sqrt(CGAL::to_double(squared_distance(prevVertex->point(), 
00157               nextVertex->point())));
00158 }
00159 
00160 void CN94Proposal::InteriorVertexDeath::execute(Coloring& c) {
00161   assert(prevVertex.valid());
00162   Coloring::VertexHandle vertex = prevVertex->getNextVertex();
00163   assert(c.deleteVertex(vertex, Coloring::DO_WITHOUT_TEST_TAG()));
00164 }
00165 
00166 void CN94Proposal::InteriorVertexDeath::undo(Coloring& c) {
00167   Coloring::IntEdgeHandle edge = prevVertex->getNextIntEdge();
00168   assert(c.splitEdge(edge, point, Coloring::DO_WITHOUT_TEST_TAG()));
00169 }
00170 
00172 
00173 void CN94Proposal::MoveInteriorVertex::reset(Coloring::VertexHandle vertex, 
00174                const Point& point) {
00175   this->vertex = vertex;
00176   oldLoc = vertex->point();
00177   newLoc = point;
00178 }
00179 
00180 void CN94Proposal::MoveInteriorVertex::execute(Coloring& c) {  
00181   assert(c.moveIntVertex(vertex, newLoc, Coloring::DO_WITHOUT_TEST_TAG()));
00182 }
00183 
00184 void CN94Proposal::MoveInteriorVertex::undo(Coloring& c) { 
00185   assert(c.moveIntVertex(vertex, oldLoc, Coloring::DO_WITHOUT_TEST_TAG()));
00186 }
00187 
00189 
00190 void CN94Proposal::MoveVertexAlongBdEdge::reset(Coloring::VertexHandle vertex, const Point& point) { 
00191   this->vertex = vertex;
00192   this->oldLoc = vertex->point();
00193   this->newLoc = point;
00194 }
00195 
00196 void CN94Proposal::MoveVertexAlongBdEdge::execute(Coloring& c) {  
00197   assert(c.moveVertexAlongBd(vertex, newLoc, Coloring::DO_WITHOUT_TEST_TAG()));
00198 }
00199 
00200 void CN94Proposal::MoveVertexAlongBdEdge::undo(Coloring& c) { 
00201   assert(c.moveVertexAlongBd(vertex, oldLoc, Coloring::DO_WITHOUT_TEST_TAG()));
00202 }
00203 
00205 
00206 void CN94Proposal::BoundaryTriangleBirth::reset(Coloring::BdEdgeHandle e,
00207             const Point& u, 
00208             const Point& v, 
00209             const Point& w) {
00210   this->edge = e;
00211   this->u = u;
00212   this->v = v;
00213   this->w = w;
00214   vh = Coloring::VertexHandle();
00215 }
00216 
00217 void CN94Proposal::BoundaryTriangleBirth::execute(Coloring& c) {
00218   assert(edge.valid());
00219   assert(c.newBoundaryTriangle(edge, u, v, w, Coloring::TEST_IF_VALID_TAG()));
00220   vh = c.newBoundaryTriangle(edge, u, v, w, Coloring::DO_WITHOUT_TEST_TAG());
00221   assert(vh.valid());
00222   edge = Coloring::BdEdgeHandle();
00223 }
00224   
00225 void CN94Proposal::BoundaryTriangleBirth::undo(Coloring& c) {
00226   assert(vh.valid());
00227   assert(c.deleteBdTriangle(vh, Coloring::DO_WITHOUT_TEST_TAG()));
00228 }
00229   
00231 
00232 void CN94Proposal::BoundaryTriangleDeath::reset(Coloring::VertexHandle vertex) {
00233   assert(vertex->type() == Coloring::Vertex::BOUNDARY);
00234   Coloring::VertexHandle u = vertex;
00235   assert(u->hasNextIntEdge());
00236   Coloring::VertexHandle w = u->getNextVertex();
00237   assert(w->type() == Coloring::Vertex::INTERIOR);
00238   Coloring::VertexHandle v = w->getNextVertex();
00239   assert(v->type() == Coloring::Vertex::BOUNDARY);
00240   vh = vertex;
00241   wp = *w;
00242   up = *u;
00243   vp = *v;
00244   // Compute the previous and next boundary vertices.
00245   if (u->getNextBdEdge()->getNextVertex() == v) {
00246     prevBoundaryVertex = u->getPrevBdEdge()->getPrevVertex();
00247     nextBoundaryVertex = v->getNextBdEdge()->getNextVertex();
00248   } else if (u->getPrevBdEdge()->getPrevVertex() == v) {
00249     prevBoundaryVertex = v->getPrevBdEdge()->getPrevVertex();
00250     nextBoundaryVertex = u->getNextBdEdge()->getNextVertex();
00251   } else
00252     assert(false);
00253 }
00254 
00255 void CN94Proposal::BoundaryTriangleDeath::execute(Coloring& c) {
00256   assert(vh.valid());
00257   assert(c.deleteBdTriangle(vh, Coloring::DO_WITHOUT_TEST_TAG()));
00258 }
00259   
00260 void CN94Proposal::BoundaryTriangleDeath::undo(Coloring& c) {
00261   assert(!vh.valid());
00262   Coloring::BdEdgeHandle e = prevBoundaryVertex->getNextBdEdge();
00263   vh = c.newBoundaryTriangle(e, up, vp, wp, Coloring::DO_WITHOUT_TEST_TAG());
00264   assert(vh.valid());
00265 }
00266   
00268 
00269 void CN94Proposal::CornerCutBirth::reset(Coloring::VertexHandle corner,
00270            const Point& u, 
00271            const Point& v) {
00272   assert(corner->type() == Coloring::Vertex::CORNER);
00273 #ifdef EXACT_GEOM_CXN
00274   assert(corner->getPrevBdEdge()->has_on(u));
00275   assert(corner->getNextBdEdge()->has_on(v));
00276 #endif
00277   this->corner = corner;
00278   this->u = u;
00279   this->v = v;
00280   vh = Coloring::VertexHandle();
00281 }
00282 
00283 void CN94Proposal::CornerCutBirth::execute(Coloring& c) {
00284   assert(corner.valid());
00285   vh = c.newCornerTriangle(corner, u, v, Coloring::DO_WITHOUT_TEST_TAG());
00286   assert(vh.valid());
00287 }
00288   
00289 void CN94Proposal::CornerCutBirth::undo(Coloring& c) {
00290   assert(vh.valid());
00291   assert(c.deleteCornerTriangle(vh, Coloring::DO_WITHOUT_TEST_TAG()));
00292 }
00293   
00295 
00296 void CN94Proposal::CornerCutDeath::reset(Coloring::VertexHandle corner) {
00297   assert(corner->type() == Coloring::Vertex::CORNER);
00298   Coloring::VertexHandle prevBdVertex = 
00299     corner->getPrevBdEdge()->getPrevVertex();
00300   Coloring::VertexHandle nextBdVertex = 
00301     corner->getNextBdEdge()->getNextVertex();
00302   assert(prevBdVertex->type() == Coloring::Vertex::BOUNDARY);
00303   assert(nextBdVertex->type() == Coloring::Vertex::BOUNDARY);
00304   if (prevBdVertex->hasNextIntEdge()) {
00305     vh = prevBdVertex;
00306     assert(vh->getNextVertex() == nextBdVertex);
00307   } else if (nextBdVertex->hasNextIntEdge()) {
00308     vh = nextBdVertex;
00309     assert(vh->getNextVertex() == prevBdVertex);
00310   } else assert(false);
00311   this->corner = corner;
00312   this->u = *prevBdVertex;
00313   this->v = *nextBdVertex;
00314 }
00315 
00316 void CN94Proposal::CornerCutDeath::execute(Coloring& c) {
00317   assert(vh.valid());
00318   assert(c.deleteCornerTriangle(vh, Coloring::DO_WITHOUT_TEST_TAG()));
00319 }
00320   
00321 void CN94Proposal::CornerCutDeath::undo(Coloring& c) {
00322   assert(!vh.valid());
00323   vh = c.newCornerTriangle(corner, u, v, Coloring::DO_WITHOUT_TEST_TAG());
00324   assert(vh.valid());
00325 }
00326   
00328 
00329 CN94Proposal::CN94Proposal(const Arak::Util::PropertyMap& props) :
00330   itd(*this), 
00331   ivd(*this),
00332   curMoveType(INVALID_MOVE),
00333   castingBoxRadius(1.0)
00334 { 
00335   using namespace Arak::Util;
00336   if (hasp(props, "arak.cn94.casting_box_side")) {
00337     assert(parse(getp(props, "arak.cn94.casting_box_side"), castingBoxRadius));
00338     assert(castingBoxRadius > 0.0);
00339     castingBoxRadius /= 2.0;
00340   } else if (hasp(props, "arak.scale")) {
00341     double scale;
00342     assert(parse(getp(props, "arak.scale"), scale));
00343     // Smart initialization (used in Nicholl's implementation)
00344     castingBoxRadius = 1.0 / (4.0 * scale * sqrt(M_PI));
00345   }
00346   // std::cerr << "Using casting box radius: " << castingBoxRadius << std::endl;
00347   // Initialize the parameters of the proposal.
00348   assert(parse(getp(props, "arak.cn94.zeta.bd_not_mr"), ZETA_BD_NOT_MR));
00349   assert(parse(getp(props, "arak.cn94.zeta.move_not_recolor"), 
00350          ZETA_MOVE_NOT_RECOLOR));
00351   assert(parse(getp(props, "arak.cn94.zeta.birth_not_death"), 
00352          ZETA_BIRTH_NOT_DEATH));
00353   assert(parse(getp(props, "arak.cn94.zeta.int_not_boundary"), 
00354          ZETA_INT_NOT_BOUNDARY));
00355   assert(parse(getp(props, "arak.cn94.zeta.bound_not_corner"), 
00356          ZETA_BOUND_NOT_CORNER));
00357   assert(parse(getp(props, "arak.cn94.zeta.ib_vertex_not_triangle"), 
00358          ZETA_IB_VERTEX_NOT_TRIANGLE));
00359   // Initialize the statistics.
00360   for (int i = 0; i < numMoveTypes; i++) {
00361     numProposed[i] = 0;
00362     numAccepted[i] = 0;
00363   }
00364 }
00365 
00366 CN94Proposal::~CN94Proposal() { }
00367 
00368 ColoringMove& CN94Proposal::move() {
00369   switch (curMoveType) {
00370   case INT_TRIANGLE_BIRTH:         return itb;
00371   case INT_TRIANGLE_DEATH:         return itd;
00372   case RECOLOR:                    return rec;
00373   case MOVE_INT_VERTEX:            return miv;
00374   case MOVE_BD_VERTEX_ALONG_BD:    return mbb;
00375   case MOVE_BD_VERTEX_PAST_CORNER: return mbc;
00376   case INT_VERTEX_BIRTH:           return ivb;
00377   case INT_VERTEX_DEATH:           return ivd;
00378   case BD_TRIANGLE_BIRTH:          return btb;
00379   case BD_TRIANGLE_DEATH:          return btd;
00380   case CORNER_CUT_BIRTH:           return ccb;
00381   case CORNER_CUT_DEATH:           return ccd;
00382   case INVALID_MOVE:
00383     return (ColoringMove&)(NullColoringMove::instance);
00384   default:
00385     assert(false);
00386   }
00387 }
00388 
00389 void CN94Proposal::sample(const Coloring& state, 
00390         Arak::Util::Random& random,
00391         bool reversible) {
00392   curMoveType = UNSPECIFIED_MOVE;
00393   if (random.uniform() < ZETA_BD_NOT_MR) {
00394     // Birth/death group
00395     if (random.uniform() < ZETA_BIRTH_NOT_DEATH) {
00396       // Birth group
00397       if (random.uniform() < ZETA_INT_NOT_BOUNDARY) {
00398   // Interior birth group
00399   if (random.uniform() < ZETA_IB_VERTEX_NOT_TRIANGLE) {
00400     // Vertex birth move
00401     sampleInteriorVertexBirth(state, random);
00402   } else {
00403     // Triangle birth move
00404     sampleInteriorTriangleBirth(state, random);
00405   }
00406       } else {
00407   // Boundary birth group
00408   if (random.uniform() < ZETA_BOUND_NOT_CORNER) {
00409     // Boundary triangle birth move
00410     sampleBoundaryTriangleBirth(state, random);
00411   } else {
00412     // Corner cut birth move
00413     sampleCornerCutBirth(state, random);
00414   }
00415       }
00416     } else {
00417       // Death group
00418       if (random.uniform() < ZETA_INT_NOT_BOUNDARY) {
00419   // Interior death group
00420   sampleInteriorDeath(state, random, reversible);
00421       } else {
00422   // Boundary death group
00423   if (random.uniform() < ZETA_BOUND_NOT_CORNER) {
00424     // Boundary edge death move
00425     sampleBoundaryTriangleDeath(state, random, reversible);
00426   } else {
00427     // Corner cut death move
00428     sampleCornerCutDeath(state, random);
00429   }
00430       }
00431     }
00432   } else {
00433     // Move/recolor group
00434     if (random.uniform() < ZETA_MOVE_NOT_RECOLOR) {
00435       // Move group
00436       if (random.uniform() < ZETA_INT_NOT_BOUNDARY) {
00437   // Relocate interior vertex move
00438   sampleMoveInteriorVertex(state, random);
00439       } else {
00440   // Relocate boundary vertex move
00441   if (random.uniform() < ZETA_BOUND_NOT_CORNER) {
00442     // Relocate vertex along boundary move
00443     sampleMoveVertexAlongBd(state, random);
00444   } else {
00445     // Relocate boundary vertex past corner move
00446     sampleMoveBdVertexPastCorner(state, random);
00447   }
00448       }
00449     } else {
00450       // Recolor move
00451       sampleRecolor(state, random);
00452     }
00453   }
00454   assert(curMoveType != UNSPECIFIED_MOVE);
00455   // Update the proposal statistics.
00456   numProposed[curMoveType]++;
00457   // std::cerr << "Proposed " << moveNames[int(curMoveType)] << std::endl;
00458 }
00459 
00461 
00462 void CN94Proposal::sampleInteriorTriangleBirth(const Coloring& state,
00463                  Arak::Util::Random& random) {
00464   // Sample the vertices of the triangle.
00465   Point u = state.randomPoint(random);
00466   Point v = sampleInCastingBox(u, random);
00467   Point w = sampleInCastingBox(u, random);
00468   if (state.interior(v) &&
00469       state.interior(w) &&
00470       state.newInteriorTriangle(u, v, w, Coloring::TEST_IF_VALID_TAG())) {
00471     curMoveType = INT_TRIANGLE_BIRTH;
00472     itb.reset(u, v, w);
00473   } else {
00474     // This sampling failed.
00475     curMoveType = INVALID_MOVE;
00476   }
00477 }
00478 
00479 void CN94Proposal::proposeBdTriangleDeath(const Coloring& state,
00480             Coloring::VertexHandle prevVertex,
00481             Coloring::VertexHandle vertex,
00482             Coloring::VertexHandle nextVertex,
00483             bool reversible) {
00484   if (reversible) {
00485     // Check to see if w satisfies the distance contraint.
00486     Segment edge(prevVertex->point(), nextVertex->point());
00487     Point p = edge.supporting_line().projection(vertex->point());
00488     if (!(CGAL::collinear_are_ordered_along_line(edge.source(),
00489              p,
00490              edge.target())
00491     &&
00492     (CGAL::squared_distance(vertex->point(), p) <= 
00493      edge.squared_length()))) {
00494       // This boundary triangle death could not be reversed by a
00495       // boundary triangle birth.
00496       curMoveType = INVALID_MOVE;
00497       return;
00498     }
00499   }
00500   if (state.deleteBdTriangle(prevVertex, Coloring::TEST_IF_VALID_TAG())) {
00501     curMoveType = BD_TRIANGLE_DEATH;
00502     btd.reset(prevVertex);
00503   } else {
00504     // The sampling failed.
00505     curMoveType = INVALID_MOVE;
00506   }
00507 }
00508 
00509 void CN94Proposal::proposeIntVertexDeath(const Coloring& state,
00510            Coloring::VertexHandle prevVertex,
00511            Coloring::VertexHandle vertex,
00512            Coloring::VertexHandle nextVertex,
00513            bool reversible) {
00514   if (reversible) {
00515     // Check that this move is reversible.
00516     Geometry::Segment edge(prevVertex->point(), nextVertex->point());
00517     Geometry::Point projection = 
00518       edge.supporting_line().projection(vertex->point());
00519     // If the vertex is farther than one half of the edge's length
00520     // from the edge that will be created, then it could not have
00521     // been created by a birth.  Also, if the vertex's projection
00522     // does not lie on the edge that will be created, then it could
00523     // not have been created by a birth.
00524     double sd = 
00525       CGAL::to_double(CGAL::squared_distance(vertex->point(), 
00526                projection));
00527     double squared_limit = CGAL::to_double(edge.squared_length()) / 4.0;
00528     if (!((sd <= squared_limit) &&
00529     CGAL::collinear_are_ordered_along_line(edge.source(),
00530              projection,
00531              edge.target()))) {
00532       // This move could not be reversed by a interior vertex birth.
00533       curMoveType = INVALID_MOVE;
00534       return;
00535     }
00536   }
00537   if (state.deleteVertex(vertex, Coloring::TEST_IF_VALID_TAG())) {
00538     curMoveType = INT_VERTEX_DEATH;
00539     ivd.reset(vertex);
00540   } else {
00541     // The sampling failed.
00542     curMoveType = INVALID_MOVE;
00543   }
00544 }
00545 
00546 void CN94Proposal::proposeIntTriangleDeath(const Coloring& state,
00547              Coloring::VertexHandle prevVertex,
00548              Coloring::VertexHandle vertex,
00549              Coloring::VertexHandle nextVertex,
00550              bool reversible) {
00551   // Check if the move is possible.
00552   if (!state.deleteIntTriangle(prevVertex, Coloring::TEST_IF_VALID_TAG())) {
00553     // The move is not valid.
00554     curMoveType = INVALID_MOVE;
00555     return;
00556   }
00557   if (!reversible) {
00558     curMoveType = INT_TRIANGLE_DEATH;
00559     itd.reset(vertex, false);
00560     return;
00561   }
00562   // Check if this move could be reversed.
00563   const Geometry::Point& u = vertex->point();
00564   const Geometry::Point& v = nextVertex->point();
00565   const Geometry::Point& w = prevVertex->point();
00566   int uvClose = inCastingBox(u, v) ? 1 : 0;
00567   int uwClose = inCastingBox(u, w) ? 1 : 0;
00568   int vwClose = inCastingBox(v, w) ? 1 : 0;
00569   int numClose = uvClose + uwClose + vwClose;
00570   if (numClose < 2) {
00571     // At least two of the edges are too long.  This triangle could
00572     // not have been generated by an interior triangle birth.
00573     curMoveType = INVALID_MOVE;
00574   } else if (numClose == 2) {
00575     // This is a "long" triangle that could have been generated by
00576     // an interior triangle birth.
00577     curMoveType = INT_TRIANGLE_DEATH;
00578     itd.reset(vertex, false);
00579   } else /* numClose == 3 */ {
00580     // This is a "short" triangle that could have been generated by
00581     // an interior triangle birth.
00582     curMoveType = INT_TRIANGLE_DEATH;
00583     itd.reset(vertex, true);
00584   }
00585 }
00586 
00587 void CN94Proposal::sampleInteriorDeath(const Coloring& state,
00588                Arak::Util::Random& random,
00589                bool reversible) {
00590   // If there are no vertices, the sampling failed.
00591   if (state.numVertices(Coloring::Vertex::INTERIOR) == 0) {
00592     curMoveType = INVALID_MOVE;
00593     return;
00594   }
00595   // Sample a vertex uniformly from the interior of the coloring.
00596   Coloring::VertexHandle vertex = 
00597     state.randomVertex(Coloring::Vertex::INTERIOR, random);
00598   // Examine the neighborhood of the vertex to determine the move
00599   // type.
00600   Coloring::VertexHandle nextVertex = vertex->getNextVertex();
00601   Coloring::VertexHandle prevVertex = vertex->getPrevVertex();
00602   if ((nextVertex->type() == Coloring::Vertex::BOUNDARY) &&
00603       (prevVertex->type() == Coloring::Vertex::BOUNDARY)) {
00604     // Both adjacent vertices are on the boundary.
00605     if ((nextVertex->getNextBdEdge()->getNextVertex() == prevVertex) ||
00606   (nextVertex->getPrevBdEdge()->getPrevVertex() == prevVertex)) {
00607       // The adjacent vertices are connected by a single boundary
00608       // edge, so this is a structure that could have been built by a
00609       // boundary triangle birth.  Propose a boundary triangle death
00610       // move.
00611       proposeBdTriangleDeath(state, prevVertex, vertex, nextVertex,
00612            reversible);
00613     } else if (nextVertex->getNextCornerVertex() != 
00614          prevVertex->getNextCornerVertex()) {
00615       // The adjacent vertices are on distinct boundary faces.  Try to
00616       // propose an interior vertex death move.  We must check that
00617       // this vertex could have been created by an interior vertex
00618       // birth move.
00619       proposeIntVertexDeath(state, prevVertex, vertex, nextVertex,
00620           reversible);
00621     } else {
00622       // The adjacent vertices are on the same boundary face but are
00623       // not connected by a single boundary edge.  In this case, the
00624       // sampling failed.
00625       curMoveType = INVALID_MOVE;
00626     }
00627   } else if ((nextVertex->type() == Coloring::Vertex::INTERIOR) &&
00628        (prevVertex->type() == Coloring::Vertex::INTERIOR) &&
00629        (nextVertex->getNextVertex() == prevVertex)) {
00630     // This vertex is part of an interior triangle.  Propose an
00631     // interior triangle death move.
00632     proposeIntTriangleDeath(state, prevVertex, vertex, nextVertex,
00633           reversible);
00634   } else {
00635     // Otherwise, propose an interior vertex death move.
00636     proposeIntVertexDeath(state, prevVertex, vertex, nextVertex,
00637         reversible);
00638   }
00639 }
00640 
00641 void CN94Proposal::sampleRecolor(const Coloring& state,
00642          Arak::Util::Random& random) {
00643   // If there are no edges, sample an invalid move.
00644   if (state.numInteriorEdges() < 2) {
00645     // This sampling failed.
00646     curMoveType = INVALID_MOVE;
00647     return;
00648   }
00649   Coloring::IntEdgeHandle edge1 = 
00650     state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
00651   Coloring::IntEdgeHandle edge2 = 
00652     state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
00653   while (edge1 == edge2)
00654     edge2 = state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
00655   bool joinSourceToSourcePossible = 
00656     !CGAL::do_intersect(Segment(*(edge1->getPrevVertex()), 
00657         *(edge2->getPrevVertex())),
00658       Segment(*(edge1->getNextVertex()), 
00659         *(edge2->getNextVertex())));
00660   bool joinSourceToTargetPossible = 
00661     !CGAL::do_intersect(Segment(*(edge1->getPrevVertex()), 
00662         *(edge2->getNextVertex())),
00663       Segment(*(edge1->getNextVertex()), 
00664         *(edge2->getPrevVertex())));
00665   assert(joinSourceToSourcePossible || joinSourceToTargetPossible);
00666   bool convex = joinSourceToSourcePossible xor joinSourceToTargetPossible;
00667   bool joinSourceToSource = 
00668     (joinSourceToSourcePossible && !joinSourceToTargetPossible) ||
00669     (joinSourceToSourcePossible && joinSourceToTargetPossible &&
00670      random.bernoulli());
00671   if (state.recolorQuadrilateral(edge1, edge2, joinSourceToSource,
00672          Coloring::TEST_IF_VALID_TAG())) {
00673     // Propose the recoloring move.
00674     curMoveType = RECOLOR;
00675     rec.reset(edge1, edge2, joinSourceToSource, convex);
00676   } else {
00677     curMoveType = INVALID_MOVE;
00678   }
00679 }
00680 
00681 void CN94Proposal::sampleMoveBdVertexPastCorner(const Coloring& state, 
00682             Arak::Util::Random& random) {
00683   // Sample a corner vertex.
00684   Coloring::VertexHandle corner = state.randomVertex(Coloring::Vertex::CORNER);
00685   // Sample an incident edge.
00686   bool useNext = random.bernoulli();
00687   Coloring::BdEdgeHandle edge = (useNext ? 
00688          corner->getNextBdEdge() : 
00689          corner->getPrevBdEdge());
00690   Coloring::VertexHandle bdVertex = (useNext ? 
00691              edge->getNextVertex() : 
00692              edge->getPrevVertex());
00693   // If the next vertex is not a boundary vertex (i.e., it is a
00694   // corner), then this sampling failed.
00695   if (bdVertex->type() != Coloring::Vertex::BOUNDARY) {
00696     curMoveType = INVALID_MOVE;
00697     return;
00698   }
00699   Coloring::VertexHandle adjVertex = (bdVertex->hasNextIntEdge() ? 
00700               bdVertex->getNextVertex() : 
00701               bdVertex->getPrevVertex());
00702   // If the adjacent vertex is a boundary vertex on the target face,
00703   // this sampling failed.
00704   if ((adjVertex->type() == Coloring::Vertex::BOUNDARY) &&
00705       ((useNext && (adjVertex->getNextCornerVertex() == corner)) ||
00706        (!useNext && (adjVertex->getPrevCornerVertex() == corner)))) {
00707     curMoveType = INVALID_MOVE;
00708     return;
00709   }
00710   // Sample a new location for the vertex on the other edge incident
00711   // to the corner.
00712   Coloring::BdEdgeHandle otherEdge = (useNext ? 
00713               corner->getPrevBdEdge() :
00714               corner->getNextBdEdge()); 
00715   Point p = otherEdge->randomPoint(random);
00716   // Check that this move is valid.
00717   if (state.moveBdVertexPastCorner(edge, p, Coloring::TEST_IF_VALID_TAG())) {
00718     curMoveType = MOVE_BD_VERTEX_PAST_CORNER;
00719     mbc.reset(edge, p);
00720   } else {
00721     // This sampling failed.
00722     curMoveType = INVALID_MOVE;
00723   }
00724 }
00725 
00726 void CN94Proposal::sampleInteriorVertexBirth(const Coloring& state,
00727                Arak::Util::Random& random) {
00728   // If there are no edges in the interior, sample an invalid move.
00729   if (state.numInteriorEdges() == 0) {
00730     curMoveType = INVALID_MOVE;
00731     return;
00732   }
00733   // Sample an edge uniformly from the interior.
00734   const Coloring::IntEdgeHandle e = 
00735     state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
00736   // Sample a point uniformly on the edge.
00737   Point q = e->randomPoint(random);
00738   // Compute the normal vector to the edge.
00739   Vector v = e->to_vector().perpendicular(CGAL::CLOCKWISE);
00740   // Normalize the vector.
00741   v = v / sqrt(CGAL::to_double(v * v));
00742   // Choose the distance from e.
00743   double halfLength = e->length() / 2.0;
00744   Point p = q + (v * random.uniform(-halfLength, halfLength));
00745   // Check that the move is valid.
00746   if (state.interior(p) &&
00747       state.splitEdge(e, p, Coloring::TEST_IF_VALID_TAG())) {
00748     curMoveType = INT_VERTEX_BIRTH;
00749     ivb.reset(e, p);
00750   } else {
00751     // This sampling failed.
00752     curMoveType = INVALID_MOVE;
00753   }
00754 }
00755 
00756 void CN94Proposal::sampleMoveInteriorVertex(const Coloring& state, 
00757               Arak::Util::Random& random) {
00758   // If there are no vertices in the interior, sample an invalid move.
00759   if (state.numVertices(Coloring::Vertex::INTERIOR) == 0) {
00760     curMoveType = INVALID_MOVE;
00761     return;
00762   }
00763   // Sample a vertex uniformly from the interior.
00764   Coloring::VertexHandle v = 
00765     state.randomVertex(Coloring::Vertex::INTERIOR, random);
00766   Point p = sampleInCastingBox(v->point(), random);
00767   // Check to see if the move is valid.
00768   if (state.interior(p) &&
00769       state.moveIntVertex(v, p, Coloring::TEST_IF_VALID_TAG())) {
00770     curMoveType = MOVE_INT_VERTEX;
00771     miv.reset(v, p);
00772   } else {
00773     // This sampling failed.
00774     curMoveType = INVALID_MOVE;
00775   }
00776 }
00777 
00778 void CN94Proposal::sampleMoveVertexAlongBd(const Coloring& state, 
00779              Arak::Util::Random& random) {
00780   // If there are no vertices on the boundary, sample an invalid move.
00781   if (state.numVertices(Coloring::Vertex::BOUNDARY) == 0) {
00782     curMoveType = INVALID_MOVE;
00783     return;
00784   }
00785   // Sample a boundary vertex uniformly.
00786   Coloring::VertexHandle v = 
00787     state.randomVertex(Coloring::Vertex::BOUNDARY, random);
00788   Point a = *(v->getPrevBdEdge()->getPrevVertex());
00789   Point b = *(v->getNextBdEdge()->getNextVertex());
00790   Geometry::Vector va(CGAL::ORIGIN, a);
00791   Geometry::Vector vb(CGAL::ORIGIN, b);
00792   Geometry::Kernel::FT x(random.uniform());
00793   Geometry::Vector vp = (va * x) + vb - (vb * x);
00794   Geometry::Point p(vp.x(), vp.y());
00795 #ifdef EXACT_GEOM_CXN
00796   assert(v->getPrevBdEdge()->has_on(p) || v->getNextBdEdge()->has_on(p));
00797 #endif
00798   // Check that the move is valid.
00799   if ((a != p) &&
00800       (b != p) &&
00801       state.moveVertexAlongBd(v, p, Coloring::TEST_IF_VALID_TAG())) {
00802     curMoveType = MOVE_BD_VERTEX_ALONG_BD;
00803     mbb.reset(v, p);
00804   } else {
00805     // The sampling failed.
00806     curMoveType = INVALID_MOVE;
00807   }
00808 }
00809 
00810 void CN94Proposal::sampleBoundaryTriangleBirth(const Coloring& state,
00811                  Arak::Util::Random& random) {
00812   // Sample the boundary edge.
00813   const Coloring::BdEdgeHandle e = 
00814     state.getBoundaryEdge(random.uniform(state.numBoundaryEdges()));
00815   // Sample the boundary vertices of the triangle.
00816   Point u = e->randomPoint(random);
00817   Point v = e->randomPoint(random);
00818   // Reject the move if the sampled points are vertices of the
00819   // boundary edge; this can happen when the boundary edge is short.
00820   if ((e->source() == u) ||
00821       (e->target() == u) ||
00822       (e->source() == v) ||
00823       (e->target() == v)) {
00824     curMoveType = INVALID_MOVE;
00825     return;
00826   }
00827   /* 
00828    * Sample the interior vertex.
00829    */
00830   // Sample a point uniformly on the new boundary edge.
00831   Point q = random.uniform(u, v);
00832   // Compute the normal vector to the edge.
00833   Vector n = e->to_vector().perpendicular(CGAL::CLOCKWISE);
00834   // Normalize the vector.
00835   n = n / sqrt(CGAL::to_double(n * n));
00836   // Choose the distance from e.
00837   double distance = 
00838     random.uniform(0.0, sqrt(CGAL::to_double(CGAL::squared_distance(u, v))));
00839   Point w = q + (n * distance);
00840   // If we chose the wrong perpendicular direction, flip it.
00841   if (!state.interior(w))
00842     w = q - n * distance;
00843   // Check that the move is valid.
00844   if ((u != v) && (v != w) && (w != u) &&
00845       state.interior(w) &&
00846       state.newBoundaryTriangle(e, u, v, w, Coloring::TEST_IF_VALID_TAG())) {
00847     curMoveType = BD_TRIANGLE_BIRTH;
00848     btb.reset(e, u, v, w);
00849   } else {
00850     // The sampling failed.
00851     curMoveType = INVALID_MOVE;
00852   }
00853 }
00854 
00855 void CN94Proposal::sampleBoundaryTriangleDeath(const Coloring& state,
00856                  Arak::Util::Random& random,
00857                  bool reversible) {
00858   // If there are no edges on the boundary, sample an invalid move.
00859   if (state.numBoundaryEdges() == 0) {
00860     curMoveType = INVALID_MOVE;
00861     return;
00862   }
00863   // Sample a boundary edge.
00864   const Coloring::BdEdgeHandle e = 
00865     state.getBoundaryEdge(random.uniform(state.numBoundaryEdges()));
00866   // Check to see if this edge is part of a boundary triangle.
00867   const Coloring::VertexHandle u = e->getPrevVertex();
00868   const Coloring::VertexHandle v = e->getNextVertex();
00869   // Make sure both vertices are boundary vertices.
00870   if ((u->type() == Coloring::Vertex::CORNER) || 
00871       (v->type() == Coloring::Vertex::CORNER)) {
00872     curMoveType = INVALID_MOVE; return;
00873   }
00874   // Make sure they are connected to a common central vertex.
00875   if ((u->hasNextIntEdge() == v->hasNextIntEdge()) ||
00876       (u->hasNextIntEdge() && 
00877        (u->getNextVertex() != v->getPrevVertex())) ||
00878       (v->hasNextIntEdge() && 
00879        (v->getNextVertex() != u->getPrevVertex()))) {
00880     curMoveType = INVALID_MOVE; return;
00881   }
00882   // Propose the boundary triangle death move.
00883   if (u->hasNextIntEdge())
00884     proposeBdTriangleDeath(state, u, u->getNextVertex(), v, reversible);
00885   else
00886     proposeBdTriangleDeath(state, v, v->getNextVertex(), u, reversible);
00887 }
00888 
00889 void CN94Proposal::sampleCornerCutBirth(const Coloring& state,
00890           Arak::Util::Random& random) {
00891   Coloring::VertexHandle corner = 
00892     state.randomVertex(Coloring::Vertex::CORNER, random);
00893   Coloring::BdEdgeHandle prevBdEdge = corner->getPrevBdEdge();
00894   Coloring::BdEdgeHandle nextBdEdge = corner->getNextBdEdge();
00895   Point u = prevBdEdge->randomPoint(random);
00896   Point v = nextBdEdge->randomPoint(random);
00897   // Check that (u, v) is a compatible edge.  Also ensure that the
00898   // sampled points are not vertices; this can happen when the
00899   // boundary edges are short.
00900   if ((u == prevBdEdge->source()) ||
00901       (u == prevBdEdge->target()) ||
00902       (v == nextBdEdge->source()) ||
00903       (v == nextBdEdge->target()) ||
00904       !state.newCornerTriangle(corner, u, v, Coloring::TEST_IF_VALID_TAG())) {
00905     // This sampling failed.
00906     curMoveType = INVALID_MOVE;
00907   } else {
00908     curMoveType = CORNER_CUT_BIRTH;
00909     ccb.reset(corner, u, v);
00910   }
00911 }
00912 
00913 void CN94Proposal::sampleCornerCutDeath(const Coloring& state,
00914           Arak::Util::Random& random) {
00915   Coloring::VertexHandle corner = 
00916     state.randomVertex(Coloring::Vertex::CORNER, random);
00917   Coloring::VertexHandle prevBdVertex = 
00918     corner->getPrevBdEdge()->getPrevVertex();
00919   Coloring::VertexHandle nextBdVertex = 
00920     corner->getNextBdEdge()->getNextVertex();
00921   if ((prevBdVertex->type() == Coloring::Vertex::BOUNDARY) &&
00922       (nextBdVertex->type() == Coloring::Vertex::BOUNDARY) &&
00923       ((prevBdVertex->hasNextIntEdge() && 
00924   (prevBdVertex->getNextVertex() == nextBdVertex) &&
00925   (state.deleteCornerTriangle(prevBdVertex, 
00926             Coloring::TEST_IF_VALID_TAG())))
00927        ||
00928        (nextBdVertex->hasNextIntEdge() && 
00929   (nextBdVertex->getNextVertex() == prevBdVertex) &&
00930   (state.deleteCornerTriangle(nextBdVertex, 
00931             Coloring::TEST_IF_VALID_TAG()))))) {
00932     ccd.reset(corner);
00933     curMoveType = CORNER_CUT_DEATH;
00934   } else {
00935     // This sampling failed.
00936     curMoveType = INVALID_MOVE;
00937   }
00938 }
00939 
00940 double CN94Proposal::ll(const Coloring& c) {
00941   switch (curMoveType) {
00942   case INT_TRIANGLE_BIRTH: {
00943     double a = castingArea();
00944     double A = c.area();
00945     return ln(ZETA_BD_NOT_MR * 
00946         ZETA_BIRTH_NOT_DEATH *
00947         ZETA_INT_NOT_BOUNDARY *
00948         (1.0 - ZETA_IB_VERTEX_NOT_TRIANGLE) * 
00949         (inCastingBox(itb.v, itb.w) ? 6.0 : 2.0) / (A * a * a));
00950   }
00951   case INT_TRIANGLE_DEATH: 
00952     // The extra factor of three is necessary because there are three
00953     // ways to propose removal of an interior triangle (one per
00954     // vertex).
00955     return ln(ZETA_BD_NOT_MR * 
00956         (1.0 - ZETA_BIRTH_NOT_DEATH) *
00957         ZETA_INT_NOT_BOUNDARY *
00958         3.0 / 
00959         double(c.numVertices(Coloring::Vertex::INTERIOR)));
00960   case RECOLOR: {
00961     int n = c.numInteriorEdges();
00962     return ln(((1.0 - ZETA_BD_NOT_MR) * 
00963          (1.0 - ZETA_MOVE_NOT_RECOLOR) *
00964          2.0 * (rec.isConvex() ? 1.0 : 0.5)) /
00965         double(n * (n - 1)));
00966   }
00967   case MOVE_INT_VERTEX: {
00968     return ln((1.0 - ZETA_BD_NOT_MR) * 
00969         ZETA_MOVE_NOT_RECOLOR *
00970         ZETA_INT_NOT_BOUNDARY /
00971         (double(c.numVertices(Coloring::Vertex::INTERIOR)) *
00972          castingArea()));
00973   }
00974   case MOVE_BD_VERTEX_ALONG_BD: {
00975     return ln((1.0 - ZETA_BD_NOT_MR) * 
00976         ZETA_MOVE_NOT_RECOLOR *
00977         (1.0 - ZETA_INT_NOT_BOUNDARY) *
00978         ZETA_BOUND_NOT_CORNER /
00979         (double(c.numVertices(Coloring::Vertex::BOUNDARY)) *
00980          (mbb.vertex->getNextBdEdge()->length() + 
00981     mbb.vertex->getPrevBdEdge()->length())));
00982   }
00983   case MOVE_BD_VERTEX_PAST_CORNER: {
00984     // Find the other edge incident to the corner.
00985     Coloring::BdEdgeHandle ep = 
00986       (mbc.edge->getPrevVertex()->type() == Coloring::Vertex::CORNER) ?
00987       mbc.edge->getPrevVertex()->getPrevBdEdge() :
00988       mbc.edge->getNextVertex()->getNextBdEdge();
00989     return ln((1.0 - ZETA_BD_NOT_MR) * 
00990         ZETA_MOVE_NOT_RECOLOR *
00991         (1.0 - ZETA_INT_NOT_BOUNDARY) *
00992         (1.0 - ZETA_BOUND_NOT_CORNER) /
00993         (2.0 * double(c.numVertices(Coloring::Vertex::CORNER)) 
00994          * ep->length()));
00995   }
00996   case INT_VERTEX_BIRTH: {
00997     return ln(ZETA_BD_NOT_MR * 
00998         ZETA_BIRTH_NOT_DEATH *
00999         ZETA_INT_NOT_BOUNDARY *
01000         ZETA_IB_VERTEX_NOT_TRIANGLE /
01001         (double(c.numInteriorEdges()) 
01002          * CGAL::to_double(squared_distance(*(ivb.prevVertex), 
01003               *(ivb.nextVertex)))));
01004   }
01005   case INT_VERTEX_DEATH: {
01006     return ln(ZETA_BD_NOT_MR * 
01007         (1.0 - ZETA_BIRTH_NOT_DEATH) *
01008         ZETA_INT_NOT_BOUNDARY /
01009         double(c.numVertices(Coloring::Vertex::INTERIOR)));
01010   }
01011   case BD_TRIANGLE_BIRTH: {
01012     double a = CGAL::to_double(btb.edge->segment().squared_length());
01013     double b = CGAL::to_double(squared_distance(btb.u, btb.v));
01014     return ln(ZETA_BD_NOT_MR * 
01015         ZETA_BIRTH_NOT_DEATH *
01016         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01017         ZETA_BOUND_NOT_CORNER *
01018         2.0 / 
01019         (double(c.numBoundaryEdges()) * a * b));
01020   }
01021   case BD_TRIANGLE_DEATH:  {
01022     return ln(// Probability proposed by interior vertex death
01023         (ZETA_BD_NOT_MR * 
01024          (1.0 - ZETA_BIRTH_NOT_DEATH) *
01025          ZETA_INT_NOT_BOUNDARY /
01026          double(c.numVertices(Coloring::Vertex::INTERIOR)))
01027         +
01028         // Probability proposed by boundary edge death
01029         (ZETA_BD_NOT_MR * 
01030          (1.0 - ZETA_BIRTH_NOT_DEATH) *
01031          (1.0 - ZETA_INT_NOT_BOUNDARY) *
01032          ZETA_BOUND_NOT_CORNER / 
01033          double(c.numBoundaryEdges())));
01034   }
01035   case CORNER_CUT_BIRTH: {
01036     double lp = ccb.corner->getPrevBdEdge()->length();
01037     double np = ccb.corner->getNextBdEdge()->length();
01038     return ln(ZETA_BD_NOT_MR * 
01039         ZETA_BIRTH_NOT_DEATH *
01040         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01041         (1.0 - ZETA_BOUND_NOT_CORNER) /
01042         (double(c.numVertices(Coloring::Vertex::CORNER)) * lp * np));    
01043   }
01044   case CORNER_CUT_DEATH:
01045     return ln(ZETA_BD_NOT_MR * 
01046         (1.0 - ZETA_BIRTH_NOT_DEATH) *
01047         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01048         (1.0 - ZETA_BOUND_NOT_CORNER) /
01049         double(c.numVertices(Coloring::Vertex::CORNER)));
01050   case INVALID_MOVE:
01051     // We want to force the sampler to reject the current move.  To do
01052     // this, we say its proposal probability is one and its reverse
01053     // proposal probability is zero.  TODO: this should be done more
01054     // cleanly.
01055     return 0.0;
01056   default:
01057     assert(false);
01058   }
01059 }
01060   
01061 double CN94Proposal::rll(const Coloring& c) {
01062   switch (curMoveType) {
01063   case INT_TRIANGLE_BIRTH:
01064     // Reverse of: INT_TRIANGLE_DEATH
01065     return ln(ZETA_BD_NOT_MR * 
01066         (1.0 - ZETA_BIRTH_NOT_DEATH) *
01067         ZETA_INT_NOT_BOUNDARY *
01068         3.0 / 
01069         double(3 + c.numVertices(Coloring::Vertex::INTERIOR)));
01070   case INT_TRIANGLE_DEATH: {
01071     // Reverse of: INT_TRIANGLE_BIRTH
01072     double a = castingArea();
01073     double A = c.area();
01074     return ln(ZETA_BD_NOT_MR * 
01075         ZETA_BIRTH_NOT_DEATH *
01076         ZETA_INT_NOT_BOUNDARY *
01077         (1.0 - ZETA_IB_VERTEX_NOT_TRIANGLE) * 
01078         (itd.isShort ? 6.0 : 2.0) / 
01079         (A * a * a));
01080   } 
01081   case RECOLOR: {
01082     // Reverse of: RECOLOR
01083     int n = c.numInteriorEdges();
01084     return ln((1.0 - ZETA_BD_NOT_MR) * 
01085         (1.0 - ZETA_MOVE_NOT_RECOLOR) *
01086         2.0 * (rec.isConvex() ? 1.0 : 0.5) /
01087         double(n * (n - 1)));
01088   }
01089   case MOVE_INT_VERTEX: {
01090     // Reverse of: MOVE_INT_VERTEX
01091     return ln((1.0 - ZETA_BD_NOT_MR) * 
01092         ZETA_MOVE_NOT_RECOLOR *
01093         ZETA_INT_NOT_BOUNDARY /
01094         (double(c.numVertices(Coloring::Vertex::INTERIOR)) *
01095          castingArea()));
01096   }
01097   case MOVE_BD_VERTEX_ALONG_BD: {
01098     // Reverse of: MOVE_BD_VERTEX_ALONG_BD
01099     return ln((1.0 - ZETA_BD_NOT_MR) * 
01100         ZETA_MOVE_NOT_RECOLOR *
01101         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01102         ZETA_BOUND_NOT_CORNER /
01103         (double(c.numVertices(Coloring::Vertex::BOUNDARY)) *
01104          (mbb.vertex->getNextBdEdge()->length() + 
01105     mbb.vertex->getPrevBdEdge()->length())));
01106   }
01107   case MOVE_BD_VERTEX_PAST_CORNER: {
01108     // Reverse of: MOVE_BD_VERTEX_PAST_CORNER
01109     Coloring::BdEdgeHandle e = mbc.edge;
01110     Coloring::BdEdgeHandle f = 
01111       ((e->getPrevVertex()->type() == Coloring::Vertex::CORNER) ?
01112        e->getNextVertex()->getNextBdEdge() :
01113        e->getPrevVertex()->getPrevBdEdge());
01114     return ln((1.0 - ZETA_BD_NOT_MR) * 
01115         ZETA_MOVE_NOT_RECOLOR *
01116         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01117         (1.0 - ZETA_BOUND_NOT_CORNER) /
01118         (2.0 * double(c.numVertices(Coloring::Vertex::CORNER)) 
01119          * (e->length() + f->length())));
01120   }
01121   case INT_VERTEX_BIRTH: {
01122     // Reverse of: INT_VERTEX_DEATH
01123     return ln(ZETA_BD_NOT_MR * 
01124         (1.0 - ZETA_BIRTH_NOT_DEATH) *
01125         ZETA_INT_NOT_BOUNDARY /
01126         double(1 + c.numVertices(Coloring::Vertex::INTERIOR)));
01127   }
01128   case INT_VERTEX_DEATH: {
01129     // Reverse of: INT_VERTEX_BIRTH
01130     double l = ivd.newEdgeLength;
01131     return ln(ZETA_BD_NOT_MR * 
01132         ZETA_BIRTH_NOT_DEATH *
01133         ZETA_INT_NOT_BOUNDARY *
01134         ZETA_IB_VERTEX_NOT_TRIANGLE /
01135         (double(c.numInteriorEdges() - 1) * l * l));
01136   }
01137   case BD_TRIANGLE_BIRTH: {
01138     // Reverse of: BD_TRIANGLE_DEATH
01139     return ln(// Probability reverse proposed by interior vertex death
01140         (ZETA_BD_NOT_MR * 
01141          (1.0 - ZETA_BIRTH_NOT_DEATH) *
01142          ZETA_INT_NOT_BOUNDARY /
01143          double(c.numVertices(Coloring::Vertex::INTERIOR) + 1))
01144         +
01145         // Probability reverse proposed by boundary edge death
01146         (ZETA_BD_NOT_MR * 
01147          (1.0 - ZETA_BIRTH_NOT_DEATH) *
01148          (1.0 - ZETA_INT_NOT_BOUNDARY) *
01149          ZETA_BOUND_NOT_CORNER / 
01150          double(c.numBoundaryEdges() + 2)));
01151   }
01152   case BD_TRIANGLE_DEATH: {
01153     // Reverse of: BD_TRIANGLE_BIRTH
01154     double a = CGAL::to_double(squared_distance(*(btd.prevBoundaryVertex),
01155             *(btd.nextBoundaryVertex)));
01156     double b = CGAL::to_double(squared_distance(btd.up, btd.vp));
01157     return ln(ZETA_BD_NOT_MR * 
01158         ZETA_BIRTH_NOT_DEATH *
01159         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01160         ZETA_BOUND_NOT_CORNER *
01161         2.0 / 
01162         (double(c.numBoundaryEdges() - 2) * a * b));
01163   }
01164   case CORNER_CUT_BIRTH: {
01165     // Reverse of: CORNER_CUT_DEATH
01166     return ln(ZETA_BD_NOT_MR * 
01167         (1.0 - ZETA_BIRTH_NOT_DEATH) *
01168         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01169         (1.0 - ZETA_BOUND_NOT_CORNER) /
01170         double(c.numVertices(Coloring::Vertex::CORNER)));
01171   }
01172   case CORNER_CUT_DEATH: {
01173     // Reverse of: CORNER_CUT_BIRTH
01174     Coloring::BdEdgeHandle prevBdEdge = ccb.corner->getPrevBdEdge();
01175     Coloring::BdEdgeHandle nextBdEdge = ccb.corner->getNextBdEdge();
01176     double lp = prevBdEdge->length() + 
01177       prevBdEdge->getPrevVertex()->getPrevBdEdge()->length();
01178     double np = nextBdEdge->length() + 
01179       nextBdEdge->getNextVertex()->getNextBdEdge()->length();
01180     return ln(ZETA_BD_NOT_MR * 
01181         ZETA_BIRTH_NOT_DEATH *
01182         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01183         (1.0 - ZETA_BOUND_NOT_CORNER) /
01184         (double(c.numVertices(Coloring::Vertex::CORNER)) * lp * np));
01185   }
01186   case INVALID_MOVE:
01187     // We want to force the sampler to reject the current move.  To do
01188     // this, we say its proposal probability is one and its reverse
01189     // proposal probability is zero.  TODO: this should be done more
01190     // cleanly.
01191     return -std::numeric_limits<double>::infinity();
01192   default:
01193     assert(false);
01194   }
01195 }
01196 
01197 ModifiedCN94Proposal::ModifiedCN94Proposal(const Arak::Util::PropertyMap& props)
01198   : CN94Proposal(props) { 
01199   // Initialize the parameters of the proposal.
01200   using namespace Arak::Util;
01201   assert(parse(getp(props, 
01202         "arak.modified_cn94.zeta.local_not_global_recolor"), 
01203          ZETA_LOCAL_NOT_GLOBAL_RECOLOR));
01204   assert(parse(getp(props, 
01205         "arak.modified_cn94.zeta.local_not_global_bd_tri_birth"), 
01206          ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH));
01207   assert(parse(getp(props, 
01208         "arak.modified_cn94.zeta.slide_not_move_int_vertex"), 
01209          ZETA_SLIDE_NOT_MOVE_INT_VERTEX));
01210 }
01211 
01212 void ModifiedCN94Proposal::sampleRecolor(const Coloring& state,
01213            Arak::Util::Random& random) {
01214   // With some probability use the global recolor move.
01215   if (random.uniform() >= ZETA_LOCAL_NOT_GLOBAL_RECOLOR) {
01216     CN94Proposal::sampleRecolor(state, random);
01217     return;
01218   }
01219   // If there are no edges, sample an invalid move.
01220   if (state.numInteriorEdges() < 2) {
01221     curMoveType = INVALID_MOVE;
01222     return;
01223   }
01224   // Sample an interior edge uniformly from the coloring.
01225   Coloring::IntEdgeHandle edge1 = 
01226     state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
01227   // Sample a cell from the interior edge index that is crossed by
01228   // this edge.
01229   const Coloring::InteriorEdge::CellEntryList& cellEntryList = 
01230     edge1->cellEntries();
01231   int numEntries = cellEntryList.size();
01232   Coloring::InteriorEdge::CellEntryList::const_iterator eit = 
01233     cellEntryList.begin();
01234   std::advance(eit, random.uniform(numEntries));
01235   const Coloring::InteriorEdge::CellEntry entry = *eit;
01236   const Coloring::InteriorEdgeIndex::Cell& cell = entry.getCell();
01237   // Get the list of edges that cross this cell.
01238   const Coloring::InteriorEdgeIndex::Cell::ItemList& intEdgeList = 
01239     cell.getItemList();
01240   int numEdges = intEdgeList.size();
01241   // If there is only one edge crossing this cell, the move is invalid.
01242   if (numEdges == 1) {
01243     curMoveType = INVALID_MOVE;
01244     return;
01245   }
01246   // Sample an edge from the list that is distinct from edge1.
01247   int i = random.uniform(numEdges - 1);
01248   typedef Coloring::InteriorEdgeIndex::Cell::ItemList::const_iterator Iterator;
01249   Coloring::IntEdgeHandle edge2;
01250   for (Iterator it = intEdgeList.begin(); it != intEdgeList.end(); ++it) {
01251     edge2 = *it;
01252     if (edge2 == edge1) {
01253       ++it; 
01254       continue;
01255     }
01256     if (i-- == 0) break;
01257   }
01258   // Sample the way in which we will recolor.
01259   bool joinSourceToSourcePossible = 
01260     !CGAL::do_intersect(Segment(*(edge1->getPrevVertex()), 
01261         *(edge2->getPrevVertex())),
01262       Segment(*(edge1->getNextVertex()), 
01263         *(edge2->getNextVertex())));
01264   bool joinSourceToTargetPossible = 
01265     !CGAL::do_intersect(Segment(*(edge1->getPrevVertex()), 
01266         *(edge2->getNextVertex())),
01267       Segment(*(edge1->getNextVertex()), 
01268         *(edge2->getPrevVertex())));
01269   assert(joinSourceToSourcePossible || joinSourceToTargetPossible);
01270   bool convex = joinSourceToSourcePossible xor joinSourceToTargetPossible;
01271   bool joinSourceToSource = 
01272     (joinSourceToSourcePossible && !joinSourceToTargetPossible) ||
01273     (joinSourceToSourcePossible && joinSourceToTargetPossible &&
01274      random.bernoulli());
01275   // Propose the recoloring move.
01276   if (state.recolorQuadrilateral(edge1, edge2, joinSourceToSource,
01277          Coloring::TEST_IF_VALID_TAG())) {
01278     // Propose the recoloring move.
01279     curMoveType = RECOLOR;
01280     rec.reset(edge1, edge2, joinSourceToSource, convex);
01281   } else {
01282     curMoveType = INVALID_MOVE;
01283   }
01284 }
01285 
01286 void ModifiedCN94Proposal::sampleBoundaryTriangleBirth(const Coloring& state,
01287                    Arak::Util::Random& random) {
01288   // With some probability use the global recolor move.
01289   if (random.uniform() >= ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH) {
01290     CN94Proposal::sampleBoundaryTriangleBirth(state, random);
01291     return;
01292   }
01293   // Sample the boundary edge.
01294   const Coloring::BdEdgeHandle e = 
01295     state.getBoundaryEdge(random.uniform(state.numBoundaryEdges()));
01296   // Sample the first boundary vertex of the triangle.
01297   Point u = e->randomPoint(random);
01298   // Compute a vector aligned with the edge of length castingBoxRadius.
01299   Vector a = e->to_vector();
01300   a = a * (castingBoxRadius / sqrt(CGAL::to_double(a * a)));
01301   // Sample the second vertex of the triangle.
01302   Point v = random.uniform(u + a, u - a);
01303   // If this point is not on the edge, the move is rejected.
01304   if (!CGAL::collinear_are_ordered_along_line(e->source(), v, e->target())) {
01305     curMoveType = INVALID_MOVE;
01306     return;
01307   }
01308   // Reject the move if the sampled points are vertices of the
01309   // boundary edge; this can happen when the boundary edge is short.
01310   if ((e->source() == u) ||
01311       (e->target() == u) ||
01312       (e->source() == v) ||
01313       (e->target() == v)) {
01314     curMoveType = INVALID_MOVE;
01315     return;
01316   }
01317   /* 
01318    * Sample the interior vertex.
01319    */
01320   // Sample a point uniformly on the new boundary edge.
01321   Point q = random.uniform(u, v);
01322   // Compute the normal vector to the edge.
01323   Vector n = e->to_vector().perpendicular(CGAL::CLOCKWISE);
01324   // Normalize the vector.
01325   n = n / sqrt(CGAL::to_double(n * n));
01326   // Choose the distance from e.
01327   double distance = 
01328     random.uniform(0.0, sqrt(CGAL::to_double(CGAL::squared_distance(u, v))));
01329   Point w = q + (n * distance);
01330   // If we chose the wrong perpendicular direction, flip it.
01331   if (!state.interior(w))
01332     w = q - n * distance;
01333   // Check that the move is valid.
01334   if ((u != v) && (v != w) && (w != u) &&
01335       state.interior(w) &&
01336       state.newBoundaryTriangle(e, u, v, w, Coloring::TEST_IF_VALID_TAG())) {
01337     curMoveType = BD_TRIANGLE_BIRTH;
01338     btb.reset(e, u, v, w);
01339   } else {
01340     // The sampling failed.
01341     curMoveType = INVALID_MOVE;
01342   }
01343 }
01344 
01349 inline double localRecolorSampleProb(const Coloring& state,
01350              Coloring::IntEdgeHandle edge1,
01351              Coloring::IntEdgeHandle edge2) {
01352   int n = state.numInteriorEdges();
01353   int k1 = edge1->cellEntries().size();
01354   int k2 = edge2->cellEntries().size();
01355   double p = 0.0;
01356   // We must iterate over all grid cells that are crossed by edge1 and
01357   // edge2.  To do this, we iterate over edge1's cells.
01358   typedef Coloring::InteriorEdgeIndex::Cell Cell;
01359   typedef Coloring::InteriorEdge::CellEntry CellEntry;
01360   typedef Coloring::InteriorEdge::CellEntryList CellEntryList;
01361   typedef CellEntryList::const_iterator CellEntryIterator;
01362   const CellEntryList& cel1 = edge1->cellEntries();
01363   for (CellEntryIterator it1 = cel1.begin(); it1 != cel1.end(); it1++) {
01364     const Cell& c1 = it1->getCell();
01365     const Cell::ItemList& edgesInCell = c1.getItemList();
01366     if (std::find(edgesInCell.begin(), 
01367       edgesInCell.end(), edge2) != edgesInCell.end()) {
01368       // This cell is crossed by edge1 and edge2.
01369       int size = edgesInCell.size();
01370       // Add in probability we first sampled edge1, then sampled this
01371       // cell from the list of cells containing edge1, then sampled
01372       // edge2 from the other edges in this cell.
01373       p += 1.0 / double(n * k1 * (size - 1));
01374       // Add in probability we first sampled edge2, then sampled this
01375       // cell from the list of cells containing edge2, then sampled
01376       // edge1 from the other edges in this cell.
01377       p += 1.0 / double(n * k2 * (size - 1));
01378     }
01379   }    
01380   return p;
01381 }
01382 
01383 void ModifiedCN94Proposal::sampleSlideInteriorVertex(const Coloring& state,
01384                  Arak::Util::Random& random) {
01385   // If there are no vertices in the interior, sample an invalid move.
01386   if (state.numVertices(Coloring::Vertex::INTERIOR) == 0) {
01387     curMoveType = INVALID_MOVE;
01388     return;
01389   }
01390   // Sample a vertex uniformly from the interior.
01391   Coloring::VertexHandle u = 
01392     state.randomVertex(Coloring::Vertex::INTERIOR, random);
01393   // Sample an edge incident to u.
01394   bool next = random.bernoulli();
01395   Coloring::IntEdgeHandle e = next ? u->getNextIntEdge() : u->getPrevIntEdge();
01396   Coloring::VertexHandle v = next ? e->getNextVertex() : e->getPrevVertex();
01397   // Sample the new location.
01398   Geometry::Vector e_vec = (v->point() - u->point());
01399   Point p = random.uniform(u->point() + (e_vec / 2.0),
01400          u->point() - e_vec);
01401   // Check to see if the move is valid.
01402   if (state.interior(p) &&
01403       state.moveIntVertex(u, p, Coloring::TEST_IF_VALID_TAG())) {
01404     curMoveType = MOVE_INT_VERTEX; // slide_not_move flag indicates slide
01405     slide_not_move = true;
01406     siv.reset(u, next, p);
01407   } else {
01408     // This sampling failed.
01409     curMoveType = INVALID_MOVE;
01410   }
01411 }
01412 
01413 void ModifiedCN94Proposal::sampleMoveInteriorVertex(const Coloring& state,
01414                 Arak::Util::Random& random) {
01415   // With some probability sample a move interior vertex move.
01416   if (random.uniform() >= ZETA_SLIDE_NOT_MOVE_INT_VERTEX) {
01417     CN94Proposal::sampleMoveInteriorVertex(state, random);
01418     slide_not_move = false;
01419     return;
01420   }
01421   // With the remaining probability, sample a slide vertex move.
01422   sampleSlideInteriorVertex(state, random);
01423 }
01424 
01425 double ModifiedCN94Proposal::ll(const Coloring& state) {
01426   if (curMoveType == RECOLOR) {
01427     int n = state.numInteriorEdges();
01428     double p = localRecolorSampleProb(state, rec.edge1, rec.edge2);
01429     return ln((1.0 - ZETA_BD_NOT_MR) * 
01430         (1.0 - ZETA_MOVE_NOT_RECOLOR) *
01431         (// Global probability
01432          ((1.0 - ZETA_LOCAL_NOT_GLOBAL_RECOLOR) *
01433     2.0 * (rec.isConvex() ? 1.0 : 0.5) /
01434     double(n * (n - 1)))
01435          + 
01436          // Local probability
01437          (ZETA_LOCAL_NOT_GLOBAL_RECOLOR * p)));
01438   } else if (curMoveType == BD_TRIANGLE_BIRTH) {
01439     int n = state.numBoundaryEdges();
01440     double a = CGAL::to_double(btb.edge->segment().squared_length());
01441     double b = CGAL::to_double(squared_distance(btb.u, btb.v));
01442     bool couldHaveBeenLocal = (b <= castingBoxRadius * castingBoxRadius);
01443     return ln(ZETA_BD_NOT_MR * 
01444         ZETA_BIRTH_NOT_DEATH *
01445         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01446         ZETA_BOUND_NOT_CORNER *
01447         (
01448          // Global probability
01449          ((1.0 - ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH) *
01450     2.0 / 
01451     (double(n) * a * b))
01452          +
01453          // Local probability
01454          (couldHaveBeenLocal ? 
01455     (ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH *
01456      2.0 / 
01457      (double(n) * sqrt(a) * 2.0 * castingBoxRadius * b)) 
01458     :
01459     0.0)));
01460   } else if (curMoveType == MOVE_INT_VERTEX) {
01461     if (slide_not_move) {
01462       // Slide interior vertex.
01463       Coloring::IntEdgeHandle e = 
01464   siv.next ? siv.vertex->getNextIntEdge() : siv.vertex->getPrevIntEdge();
01465       return ln((1.0 - ZETA_BD_NOT_MR) * 
01466     ZETA_MOVE_NOT_RECOLOR *
01467     ZETA_INT_NOT_BOUNDARY *
01468     ZETA_SLIDE_NOT_MOVE_INT_VERTEX /
01469     (double(state.numVertices(Coloring::Vertex::INTERIOR)) /
01470      (3.0 * e->length())));
01471       // The factor of 3 comes from 2 (edges) * (1.5 * length)
01472     } else {
01473       // Move interior vertex.
01474       return ln((1.0 - ZETA_BD_NOT_MR) * 
01475     ZETA_MOVE_NOT_RECOLOR *
01476     ZETA_INT_NOT_BOUNDARY *
01477     (1.0 - ZETA_SLIDE_NOT_MOVE_INT_VERTEX) /
01478     (double(state.numVertices(Coloring::Vertex::INTERIOR)) *
01479      castingArea()));
01480     }
01481   } else
01482     return CN94Proposal::ll(state);
01483 }
01484   
01485 double ModifiedCN94Proposal::rll(const Coloring& state) {
01486   if (curMoveType == RECOLOR) {
01487     // Reverse of: RECOLOR
01488     int n = state.numInteriorEdges();
01489     double p = localRecolorSampleProb(state, rec.edge1, rec.edge2);
01490     return ln((1.0 - ZETA_BD_NOT_MR) * 
01491         (1.0 - ZETA_MOVE_NOT_RECOLOR) *
01492         (// Global probability
01493          ((1.0 - ZETA_LOCAL_NOT_GLOBAL_RECOLOR) *
01494     2.0 * (rec.isConvex() ? 1.0 : 0.5) /
01495     double(n * (n - 1)))
01496          + 
01497          // Local probability
01498          (ZETA_LOCAL_NOT_GLOBAL_RECOLOR * p)));
01499   } else if (curMoveType == BD_TRIANGLE_DEATH) {
01500     // Reverse of: BD_TRIANGLE_BIRTH
01501     int n = state.numBoundaryEdges() - 2;
01502     double a = CGAL::to_double(squared_distance(*(btd.prevBoundaryVertex),
01503             *(btd.nextBoundaryVertex)));
01504     double b = CGAL::to_double(squared_distance(btd.up, btd.vp));
01505     bool couldHaveBeenLocal = (b <= castingBoxRadius * castingBoxRadius);
01506     return ln(ZETA_BD_NOT_MR * 
01507         ZETA_BIRTH_NOT_DEATH *
01508         (1.0 - ZETA_INT_NOT_BOUNDARY) *
01509         ZETA_BOUND_NOT_CORNER *
01510         (
01511          // Global probability
01512          ((1.0 - ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH) *
01513     2.0 / 
01514     (double(n) * a * b))
01515          +
01516          // Local probability
01517          (couldHaveBeenLocal ? 
01518     (ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH *
01519      2.0 / 
01520      (double(n) * 
01521       sqrt(a) * 2.0 * castingBoxRadius * b)) 
01522     :
01523     0.0)));
01524   } else if (curMoveType == MOVE_INT_VERTEX) {
01525     if (slide_not_move) {
01526       // Reverse of: SLIDE_INT_VERTEX (= MOVE_INT_VERTEX + flag)
01527       Coloring::VertexHandle nbr = 
01528   siv.next ? siv.vertex->getNextVertex() : siv.vertex->getPrevVertex();
01529       double new_length = 
01530   sqrt(CGAL::to_double(CGAL::squared_distance(siv.newLoc, 
01531                 nbr->point())));
01532       return ln((1.0 - ZETA_BD_NOT_MR) * 
01533     ZETA_MOVE_NOT_RECOLOR *
01534     ZETA_INT_NOT_BOUNDARY *
01535     ZETA_SLIDE_NOT_MOVE_INT_VERTEX /
01536     (double(state.numVertices(Coloring::Vertex::INTERIOR)) /
01537      (3.0 * new_length)));
01538     } else {
01539       // Reverse of: MOVE_INT_VERTEX
01540       return ln((1.0 - ZETA_BD_NOT_MR) * 
01541     ZETA_MOVE_NOT_RECOLOR *
01542     ZETA_INT_NOT_BOUNDARY *
01543     (1.0 - ZETA_SLIDE_NOT_MOVE_INT_VERTEX) /
01544     (double(state.numVertices(Coloring::Vertex::INTERIOR)) *
01545      castingArea()));
01546     }
01547   } else
01548     return CN94Proposal::rll(state);
01549 }

Generated on Wed May 25 14:39:15 2005 for Arak by doxygen 1.3.6