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
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
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
00344 castingBoxRadius = 1.0 / (4.0 * scale * sqrt(M_PI));
00345 }
00346
00347
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
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
00395 if (random.uniform() < ZETA_BIRTH_NOT_DEATH) {
00396
00397 if (random.uniform() < ZETA_INT_NOT_BOUNDARY) {
00398
00399 if (random.uniform() < ZETA_IB_VERTEX_NOT_TRIANGLE) {
00400
00401 sampleInteriorVertexBirth(state, random);
00402 } else {
00403
00404 sampleInteriorTriangleBirth(state, random);
00405 }
00406 } else {
00407
00408 if (random.uniform() < ZETA_BOUND_NOT_CORNER) {
00409
00410 sampleBoundaryTriangleBirth(state, random);
00411 } else {
00412
00413 sampleCornerCutBirth(state, random);
00414 }
00415 }
00416 } else {
00417
00418 if (random.uniform() < ZETA_INT_NOT_BOUNDARY) {
00419
00420 sampleInteriorDeath(state, random, reversible);
00421 } else {
00422
00423 if (random.uniform() < ZETA_BOUND_NOT_CORNER) {
00424
00425 sampleBoundaryTriangleDeath(state, random, reversible);
00426 } else {
00427
00428 sampleCornerCutDeath(state, random);
00429 }
00430 }
00431 }
00432 } else {
00433
00434 if (random.uniform() < ZETA_MOVE_NOT_RECOLOR) {
00435
00436 if (random.uniform() < ZETA_INT_NOT_BOUNDARY) {
00437
00438 sampleMoveInteriorVertex(state, random);
00439 } else {
00440
00441 if (random.uniform() < ZETA_BOUND_NOT_CORNER) {
00442
00443 sampleMoveVertexAlongBd(state, random);
00444 } else {
00445
00446 sampleMoveBdVertexPastCorner(state, random);
00447 }
00448 }
00449 } else {
00450
00451 sampleRecolor(state, random);
00452 }
00453 }
00454 assert(curMoveType != UNSPECIFIED_MOVE);
00455
00456 numProposed[curMoveType]++;
00457
00458 }
00459
00461
00462 void CN94Proposal::sampleInteriorTriangleBirth(const Coloring& state,
00463 Arak::Util::Random& random) {
00464
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
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
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
00495
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
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
00516 Geometry::Segment edge(prevVertex->point(), nextVertex->point());
00517 Geometry::Point projection =
00518 edge.supporting_line().projection(vertex->point());
00519
00520
00521
00522
00523
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
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
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
00552 if (!state.deleteIntTriangle(prevVertex, Coloring::TEST_IF_VALID_TAG())) {
00553
00554 curMoveType = INVALID_MOVE;
00555 return;
00556 }
00557 if (!reversible) {
00558 curMoveType = INT_TRIANGLE_DEATH;
00559 itd.reset(vertex, false);
00560 return;
00561 }
00562
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
00572
00573 curMoveType = INVALID_MOVE;
00574 } else if (numClose == 2) {
00575
00576
00577 curMoveType = INT_TRIANGLE_DEATH;
00578 itd.reset(vertex, false);
00579 } else {
00580
00581
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
00591 if (state.numVertices(Coloring::Vertex::INTERIOR) == 0) {
00592 curMoveType = INVALID_MOVE;
00593 return;
00594 }
00595
00596 Coloring::VertexHandle vertex =
00597 state.randomVertex(Coloring::Vertex::INTERIOR, random);
00598
00599
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
00605 if ((nextVertex->getNextBdEdge()->getNextVertex() == prevVertex) ||
00606 (nextVertex->getPrevBdEdge()->getPrevVertex() == prevVertex)) {
00607
00608
00609
00610
00611 proposeBdTriangleDeath(state, prevVertex, vertex, nextVertex,
00612 reversible);
00613 } else if (nextVertex->getNextCornerVertex() !=
00614 prevVertex->getNextCornerVertex()) {
00615
00616
00617
00618
00619 proposeIntVertexDeath(state, prevVertex, vertex, nextVertex,
00620 reversible);
00621 } else {
00622
00623
00624
00625 curMoveType = INVALID_MOVE;
00626 }
00627 } else if ((nextVertex->type() == Coloring::Vertex::INTERIOR) &&
00628 (prevVertex->type() == Coloring::Vertex::INTERIOR) &&
00629 (nextVertex->getNextVertex() == prevVertex)) {
00630
00631
00632 proposeIntTriangleDeath(state, prevVertex, vertex, nextVertex,
00633 reversible);
00634 } else {
00635
00636 proposeIntVertexDeath(state, prevVertex, vertex, nextVertex,
00637 reversible);
00638 }
00639 }
00640
00641 void CN94Proposal::sampleRecolor(const Coloring& state,
00642 Arak::Util::Random& random) {
00643
00644 if (state.numInteriorEdges() < 2) {
00645
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
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
00684 Coloring::VertexHandle corner = state.randomVertex(Coloring::Vertex::CORNER);
00685
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
00694
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
00703
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
00711
00712 Coloring::BdEdgeHandle otherEdge = (useNext ?
00713 corner->getPrevBdEdge() :
00714 corner->getNextBdEdge());
00715 Point p = otherEdge->randomPoint(random);
00716
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
00722 curMoveType = INVALID_MOVE;
00723 }
00724 }
00725
00726 void CN94Proposal::sampleInteriorVertexBirth(const Coloring& state,
00727 Arak::Util::Random& random) {
00728
00729 if (state.numInteriorEdges() == 0) {
00730 curMoveType = INVALID_MOVE;
00731 return;
00732 }
00733
00734 const Coloring::IntEdgeHandle e =
00735 state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
00736
00737 Point q = e->randomPoint(random);
00738
00739 Vector v = e->to_vector().perpendicular(CGAL::CLOCKWISE);
00740
00741 v = v / sqrt(CGAL::to_double(v * v));
00742
00743 double halfLength = e->length() / 2.0;
00744 Point p = q + (v * random.uniform(-halfLength, halfLength));
00745
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
00752 curMoveType = INVALID_MOVE;
00753 }
00754 }
00755
00756 void CN94Proposal::sampleMoveInteriorVertex(const Coloring& state,
00757 Arak::Util::Random& random) {
00758
00759 if (state.numVertices(Coloring::Vertex::INTERIOR) == 0) {
00760 curMoveType = INVALID_MOVE;
00761 return;
00762 }
00763
00764 Coloring::VertexHandle v =
00765 state.randomVertex(Coloring::Vertex::INTERIOR, random);
00766 Point p = sampleInCastingBox(v->point(), random);
00767
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
00774 curMoveType = INVALID_MOVE;
00775 }
00776 }
00777
00778 void CN94Proposal::sampleMoveVertexAlongBd(const Coloring& state,
00779 Arak::Util::Random& random) {
00780
00781 if (state.numVertices(Coloring::Vertex::BOUNDARY) == 0) {
00782 curMoveType = INVALID_MOVE;
00783 return;
00784 }
00785
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
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
00806 curMoveType = INVALID_MOVE;
00807 }
00808 }
00809
00810 void CN94Proposal::sampleBoundaryTriangleBirth(const Coloring& state,
00811 Arak::Util::Random& random) {
00812
00813 const Coloring::BdEdgeHandle e =
00814 state.getBoundaryEdge(random.uniform(state.numBoundaryEdges()));
00815
00816 Point u = e->randomPoint(random);
00817 Point v = e->randomPoint(random);
00818
00819
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
00829
00830
00831 Point q = random.uniform(u, v);
00832
00833 Vector n = e->to_vector().perpendicular(CGAL::CLOCKWISE);
00834
00835 n = n / sqrt(CGAL::to_double(n * n));
00836
00837 double distance =
00838 random.uniform(0.0, sqrt(CGAL::to_double(CGAL::squared_distance(u, v))));
00839 Point w = q + (n * distance);
00840
00841 if (!state.interior(w))
00842 w = q - n * distance;
00843
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
00851 curMoveType = INVALID_MOVE;
00852 }
00853 }
00854
00855 void CN94Proposal::sampleBoundaryTriangleDeath(const Coloring& state,
00856 Arak::Util::Random& random,
00857 bool reversible) {
00858
00859 if (state.numBoundaryEdges() == 0) {
00860 curMoveType = INVALID_MOVE;
00861 return;
00862 }
00863
00864 const Coloring::BdEdgeHandle e =
00865 state.getBoundaryEdge(random.uniform(state.numBoundaryEdges()));
00866
00867 const Coloring::VertexHandle u = e->getPrevVertex();
00868 const Coloring::VertexHandle v = e->getNextVertex();
00869
00870 if ((u->type() == Coloring::Vertex::CORNER) ||
00871 (v->type() == Coloring::Vertex::CORNER)) {
00872 curMoveType = INVALID_MOVE; return;
00873 }
00874
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
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
00898
00899
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
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
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
00953
00954
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
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(
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
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
01052
01053
01054
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
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
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
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
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
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
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
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
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
01139 return ln(
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
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
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
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
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
01188
01189
01190
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
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
01215 if (random.uniform() >= ZETA_LOCAL_NOT_GLOBAL_RECOLOR) {
01216 CN94Proposal::sampleRecolor(state, random);
01217 return;
01218 }
01219
01220 if (state.numInteriorEdges() < 2) {
01221 curMoveType = INVALID_MOVE;
01222 return;
01223 }
01224
01225 Coloring::IntEdgeHandle edge1 =
01226 state.getInteriorEdge(random.uniform(state.numInteriorEdges()));
01227
01228
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
01238 const Coloring::InteriorEdgeIndex::Cell::ItemList& intEdgeList =
01239 cell.getItemList();
01240 int numEdges = intEdgeList.size();
01241
01242 if (numEdges == 1) {
01243 curMoveType = INVALID_MOVE;
01244 return;
01245 }
01246
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
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
01276 if (state.recolorQuadrilateral(edge1, edge2, joinSourceToSource,
01277 Coloring::TEST_IF_VALID_TAG())) {
01278
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
01289 if (random.uniform() >= ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH) {
01290 CN94Proposal::sampleBoundaryTriangleBirth(state, random);
01291 return;
01292 }
01293
01294 const Coloring::BdEdgeHandle e =
01295 state.getBoundaryEdge(random.uniform(state.numBoundaryEdges()));
01296
01297 Point u = e->randomPoint(random);
01298
01299 Vector a = e->to_vector();
01300 a = a * (castingBoxRadius / sqrt(CGAL::to_double(a * a)));
01301
01302 Point v = random.uniform(u + a, u - a);
01303
01304 if (!CGAL::collinear_are_ordered_along_line(e->source(), v, e->target())) {
01305 curMoveType = INVALID_MOVE;
01306 return;
01307 }
01308
01309
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
01319
01320
01321 Point q = random.uniform(u, v);
01322
01323 Vector n = e->to_vector().perpendicular(CGAL::CLOCKWISE);
01324
01325 n = n / sqrt(CGAL::to_double(n * n));
01326
01327 double distance =
01328 random.uniform(0.0, sqrt(CGAL::to_double(CGAL::squared_distance(u, v))));
01329 Point w = q + (n * distance);
01330
01331 if (!state.interior(w))
01332 w = q - n * distance;
01333
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
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
01357
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
01369 int size = edgesInCell.size();
01370
01371
01372
01373 p += 1.0 / double(n * k1 * (size - 1));
01374
01375
01376
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
01386 if (state.numVertices(Coloring::Vertex::INTERIOR) == 0) {
01387 curMoveType = INVALID_MOVE;
01388 return;
01389 }
01390
01391 Coloring::VertexHandle u =
01392 state.randomVertex(Coloring::Vertex::INTERIOR, random);
01393
01394 bool next = random.bernoulli();
01395 Coloring::IntEdgeHandle e = next ? u->getNextIntEdge() : u->getPrevIntEdge();
01396 Coloring::VertexHandle v = next ? e->getNextVertex() : e->getPrevVertex();
01397
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
01402 if (state.interior(p) &&
01403 state.moveIntVertex(u, p, Coloring::TEST_IF_VALID_TAG())) {
01404 curMoveType = MOVE_INT_VERTEX;
01405 slide_not_move = true;
01406 siv.reset(u, next, p);
01407 } else {
01408
01409 curMoveType = INVALID_MOVE;
01410 }
01411 }
01412
01413 void ModifiedCN94Proposal::sampleMoveInteriorVertex(const Coloring& state,
01414 Arak::Util::Random& random) {
01415
01416 if (random.uniform() >= ZETA_SLIDE_NOT_MOVE_INT_VERTEX) {
01417 CN94Proposal::sampleMoveInteriorVertex(state, random);
01418 slide_not_move = false;
01419 return;
01420 }
01421
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 (
01432 ((1.0 - ZETA_LOCAL_NOT_GLOBAL_RECOLOR) *
01433 2.0 * (rec.isConvex() ? 1.0 : 0.5) /
01434 double(n * (n - 1)))
01435 +
01436
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
01449 ((1.0 - ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH) *
01450 2.0 /
01451 (double(n) * a * b))
01452 +
01453
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
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
01472 } else {
01473
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
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 (
01493 ((1.0 - ZETA_LOCAL_NOT_GLOBAL_RECOLOR) *
01494 2.0 * (rec.isConvex() ? 1.0 : 0.5) /
01495 double(n * (n - 1)))
01496 +
01497
01498 (ZETA_LOCAL_NOT_GLOBAL_RECOLOR * p)));
01499 } else if (curMoveType == BD_TRIANGLE_DEATH) {
01500
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
01512 ((1.0 - ZETA_LOCAL_NOT_GLOBAL_BD_TRI_BIRTH) *
01513 2.0 /
01514 (double(n) * a * b))
01515 +
01516
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
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
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 }