00001 #include "PullMoveSet.hh"
00002 #include "NeighborVector.hh"
00003 #include "LatticeProtein_Ipnt.hh"
00004
00005 namespace biu
00006 {
00007 PullMoveSet::PullMoveDecoder::PullMoveDecoder(const LatticeModel* const lattice_)
00008 : lattice(lattice_)
00009 {
00010 LatticeNeighborhood neighbors = lattice->getNeighborhood();
00011
00012
00013 for (LatticeNeighborhood::const_iterator it = neighbors.begin();
00014 it != neighbors.end(); it++)
00015 {
00016 neighDirections.push_back(*it);
00017 }
00018 directionNumber = neighDirections.size();
00019
00020
00021
00022
00023
00024 for (LatticeNeighborhood::const_iterator direction = neighbors.begin();
00025 direction != neighbors.end(); direction++)
00026 {
00027 std::vector< std::vector< IntPoint > > stdMoves;
00028
00029 for (LatticeNeighborhood::const_iterator nbi = neighbors.begin();
00030 nbi != neighbors.end(); nbi++)
00031 {
00032
00033 if (*nbi != *direction)
00034 for (LatticeNeighborhood::const_iterator nb = neighbors.begin();
00035 nb != neighbors.end(); nb++)
00036 {
00037
00038
00039 if ((*direction + *nb) != IntPoint(0,0,0) &&
00040 lattice->areNeighbored( *nbi, (*direction + *nb) ))
00041 {
00042 std::vector< IntPoint > clvec;
00043 clvec.push_back( *nbi );
00044 clvec.push_back( (*direction + *nb) );
00045 stdMoves.push_back( clvec );
00046 }
00047 }
00048 }
00049 stdPulls.push_back( stdMoves );
00050 }
00051 stdPullNumber = stdPulls.at(0).size();
00052
00053
00054 for (LatticeNeighborhood::const_iterator nb1 = neighbors.begin();
00055 nb1 != neighbors.end(); nb1++)
00056 {
00057 for (LatticeNeighborhood::const_iterator nb2 = neighbors.begin();
00058 nb2 != neighbors.end(); nb2++)
00059 {
00060 if ((*nb2 + *nb1) != IntPoint(0,0,0))
00061 {
00062 IPointVec pullVec;
00063 pullVec.push_back(*nb1);
00064 pullVec.push_back(*nb1 + *nb2);
00065 endPulls.push_back(pullVec);
00066 }
00067 }
00068 }
00069 endPullNumber = (directionNumber-1)*(directionNumber-1);
00070 }
00071
00072 void
00073 PullMoveSet::PullMoveDecoder::lookupMove(const size_t& todoSize,
00074 size_t& moveIndex, bool& pullFront,
00075 bool& stdPull, size_t& movePosition) const
00076 {
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 if (moveIndex < endPullNumber)
00091 {
00092
00093 pullFront=true;
00094 stdPull=false;
00095 movePosition=todoSize-1;
00096 return;
00097 }
00098 else if (moveIndex < endPullNumber*2)
00099 {
00100
00101 pullFront=false;
00102 stdPull=false;
00103 movePosition=0;
00104 moveIndex-=endPullNumber;
00105 return;
00106 }
00107 else
00108 {
00109
00110 stdPull = true;
00111 moveIndex -= endPullNumber*2;
00112 if (moveIndex < stdPullNumber)
00113 {
00114
00115 pullFront = true;
00116 movePosition = 0;
00117 return;
00118 }
00119 else if (moveIndex < stdPullNumber*2)
00120 {
00121
00122 moveIndex -= stdPullNumber;
00123 pullFront = false;
00124 movePosition = todoSize-1;
00125 return;
00126 }
00127 else
00128 {
00129
00130 moveIndex -= stdPullNumber*2;
00131 movePosition = 1 + moveIndex/(2*stdPullNumber);
00132 pullFront = (moveIndex % (2*stdPullNumber)) < stdPullNumber ?
00133 true : false;
00134 moveIndex = moveIndex % stdPullNumber;
00135 return;
00136 }
00137 }
00138 }
00139
00140 IPointVec
00141 PullMoveSet::PullMoveDecoder::lookupEndMove(const IntPoint& rootpoint,
00142 const size_t& moveIndex) const
00143 {
00144 IPointVec movePositions;
00145 movePositions.push_back(endPulls.at(moveIndex).at(0) + rootpoint);
00146 movePositions.push_back(endPulls.at(moveIndex).at(1) + rootpoint);
00147 return movePositions;
00148 }
00149
00150 IPointVec
00151 PullMoveSet::PullMoveDecoder::lookupStdMove(const IntPoint& pullPoint,
00152 const IntPoint& fixedPoint,
00153 const size_t& moveIndex) const
00154 {
00155 const IntPoint moveDirection = fixedPoint - pullPoint;
00156
00157 for (size_t i = 0; i < directionNumber; i++)
00158 {
00159
00160 if (neighDirections.at(i) == moveDirection)
00161 {
00162 return stdPulls.at(i).at(moveIndex);
00163 }
00164 }
00165
00166 return IPointVec();
00167 }
00168
00169 size_t
00170 PullMoveSet::PullMoveDecoder::getMoveNumber(const size_t proteinLength) const
00171 {
00172 return endPullNumber*2 +
00173 (proteinLength-1)*stdPullNumber*2;
00174 }
00175
00176 const LatticeModel* const
00177 PullMoveSet::PullMoveDecoder::getLattice(void) const {
00178 return lattice;
00179 }
00180
00181 PullMoveSet::PullMoveSet(const LatticeModel* lattice)
00182 : LatticeMoveSet(lattice),
00183 decoder(new PullMoveSet::PullMoveDecoder(lattice)),
00184 decoderIsShared(false)
00185 {
00186 undoRec.lastChangedObject = NULL;
00187 }
00188
00189 PullMoveSet::PullMoveSet(PullMoveSet::PullMoveDecoder* decoder_,
00190 const bool decoderIsShared_ )
00191 : LatticeMoveSet(decoder_->getLattice()),
00192 decoder(decoder_),
00193 decoderIsShared(decoderIsShared_)
00194 {
00195 if (!decoderIsShared) {
00196 decoder = new PullMoveSet::PullMoveDecoder(*decoder_);
00197 }
00198 undoRec.lastChangedObject = NULL;
00199 }
00200
00201 PullMoveSet*
00202 PullMoveSet::clone() {
00203 return new PullMoveSet(*this);
00204 }
00205
00206 PullMoveSet::PullMoveSet(const PullMoveSet& moveSet)
00207 : LatticeMoveSet(moveSet.lattice),
00208 undoRec(moveSet.undoRec),
00209 decoder(moveSet.decoder),
00210 decoderIsShared(moveSet.decoderIsShared)
00211 {
00212 if (!decoderIsShared) {
00213 decoder = new PullMoveSet::PullMoveDecoder(*(moveSet.decoder));
00214 }
00215 }
00216
00217 PullMoveSet&
00218 PullMoveSet::operator=(const PullMoveSet& moveSet2) {
00219 if (this != &moveSet2) {
00220 assertbiu(decoderIsShared == moveSet2.decoderIsShared, "both move sets have either to share or not");
00221 lattice = moveSet2.lattice;
00222 if (decoderIsShared) {
00223 decoder = moveSet2.decoder;
00224 } else {
00225 delete decoder;
00226 decoder = new PullMoveSet::PullMoveDecoder(*(moveSet2.decoder));
00227 }
00228 undoRec = moveSet2.undoRec;
00229 }
00230 return *this;
00231 }
00232
00233 PullMoveSet::~PullMoveSet()
00234 {
00235 if (!decoderIsShared)
00236 delete decoder;
00237 }
00238
00239 LatticeProtein*
00240 PullMoveSet::applyMove(const LatticeProtein* const todo,
00241 const size_t moveIndex) {
00242
00243
00244 LatticeProtein_Ipnt* l = new LatticeProtein_Ipnt(*todo);
00245 LatticeProtein* l2 = applyMoveInPlace(l, moveIndex);
00246
00247
00248 if (l2 == NULL) delete l;
00249
00250 return l2;
00251 }
00252
00253 LatticeProtein*
00254 PullMoveSet::applyMoveInPlace(LatticeProtein* _todo,
00255 const size_t moveIndex_)
00256 {
00257 size_t moveIndex = moveIndex_;
00258
00259 LatticeProtein_Ipnt* todo = dynamic_cast<LatticeProtein_Ipnt*>(_todo);
00260 assertbiu(todo!=NULL,
00261 "Downcasting to LatticeProtein_Ipnt failed miserably.");
00262
00263 const size_t todoSize = todo->getSequence().size();
00264
00265 assertbiu(moveIndex >=0 && moveIndex < getMoveNumber(todo),
00266 "The pull move moveIndex has to be in [0, number of available moves)."
00267 << getMoveNumber(todo));
00268
00269 undoRec.hasChanged = false;
00270
00271
00272 bool pullFront;
00273 bool stdPull;
00274 size_t position;
00275 decoder->lookupMove(todoSize, moveIndex, pullFront, stdPull, position);
00276
00277
00278
00279 const RelativeInt relPos(position, pullFront);
00280 const RelativeInt relLastElement((pullFront ? 0 : todoSize-1), pullFront);
00281
00282
00283 const IPointVec* const todoConstPoints = todo->getPointsRef();
00284
00285 IPointVec* const todoPoints = todo->getPointsRef();
00286
00287
00288 if (!stdPull)
00289 {
00290 IPointVec pullPoints =
00291 decoder->lookupEndMove(todoConstPoints->at(position),
00292 moveIndex);
00293
00294
00295 for (IPointVec::const_iterator it = todoConstPoints->begin();
00296 it != todoConstPoints->end(); it++)
00297 {
00298
00299 if ( (*it == pullPoints.at(0)) || (*it == pullPoints.at(1)) )
00300 return NULL;
00301 }
00302
00303
00304 undoRec.hasChanged = true;
00305 undoRec.lastChangedObject = todo;
00306 undoRec.position = position;
00307 undoRec.pullFront = pullFront;
00308
00309
00310 if (lattice->areNeighbored( pullPoints.at(0),
00311 todoPoints->at(relPos-2)) ) {
00312 undoRec.lastPullPosition = relPos-1;
00313 }
00314 else {
00315 undoRec.lastPullPosition = relLastElement.getValue();
00316 for (RelativeInt i(position, pullFront); i>= relLastElement+3; i--)
00317 {
00318 if (lattice->areNeighbored( todoPoints->at(i.getValue()),
00319 todoPoints->at(i-3))) {
00320 undoRec.lastPullPosition = i-2;
00321 break;
00322 }
00323 }
00324 }
00325 undoRec.lostPos0 = todoPoints->at(undoRec.lastPullPosition);
00326 undoRec.lostPos1 = todoPoints->at(RelativeInt(
00327 undoRec.lastPullPosition,
00328 pullFront)+1);
00329
00330
00331 for (RelativeInt i(undoRec.lastPullPosition, pullFront);
00332 i <= relPos -2; i++)
00333 {
00334 todoPoints->at(i.getValue()) = todoPoints->at(i+2);
00335 }
00336
00337 todoPoints->at(relPos-1) = pullPoints.at(0);
00338 todoPoints->at(relPos.getValue()) = pullPoints.at(1);
00339
00340 return todo;
00341 }
00342
00343
00344 const IntPoint pullPoint = todoConstPoints->at(position);
00345 const IntPoint fixedPoint = todoConstPoints->at(relPos + 1);
00346
00347
00348 const IPointVec clvec =
00349 decoder->lookupStdMove(pullPoint, fixedPoint, moveIndex);
00350 const IntPoint c = clvec[0] + pullPoint;
00351 const IntPoint l = clvec[1] + pullPoint;
00352
00353
00354
00355
00356
00357 if ( (pullFront && position == 0)
00358 || (!pullFront && position == todoSize-1)
00359 || (c==todoConstPoints->at(relPos - 1)) )
00360
00361 {
00362 for (IPointVec::const_iterator it = todoConstPoints->begin();
00363 it != todoConstPoints->end(); it++)
00364 {
00365
00366 if ((*it) == l) return NULL;
00367 }
00368 }
00369
00370 else
00371 {
00372 for (IPointVec::const_iterator it = todoConstPoints->begin();
00373 it != todoConstPoints->end(); it++)
00374 {
00375
00376 if (((*it) == l) || ((*it) == c)) return NULL;
00377 }
00378 }
00379
00380
00381 int lastPullPosition=-1;
00382 bool lastPullPositionFound = false;
00383
00384
00385
00386
00387 if (relPos <= relLastElement + 1)
00388 {
00389 lastPullPosition = relLastElement.getValue();
00390 lastPullPositionFound = true;
00391 }
00392
00393 else
00394 {
00395
00396 if (lattice->areNeighbored(c, todoConstPoints->at(relPos-2)))
00397 {
00398
00399 lastPullPosition = relPos-1;
00400 lastPullPositionFound = true;
00401 }
00402 }
00403
00404 if (relPos >= relLastElement + 3
00405 && !lastPullPositionFound)
00406 {
00407
00408 for (RelativeInt i(position, pullFront);
00409 (relLastElement <= i-3) && !lastPullPositionFound; i--)
00410 {
00411 if (lattice->areNeighbored(
00412 todoPoints->at(i.getValue()),
00413 todoPoints->at(i-3)))
00414 {
00415
00416 lastPullPosition = i-2;
00417 lastPullPositionFound = true;
00418 }
00419 }
00420 }
00421 if (!lastPullPositionFound) lastPullPosition = relLastElement.getValue();
00422 assertbiu(lastPullPosition!=-1,
00423 "Unhandled case in PullMoveSet move calculation.");
00424
00425
00426 undoRec.lastChangedObject = todo;
00427 undoRec.hasChanged = true;
00428 undoRec.pullFront = pullFront;
00429 undoRec.position = position;
00430 undoRec.lastPullPosition = lastPullPosition;
00431
00432
00433 const RelativeInt relLastPullPosition(lastPullPosition, pullFront);
00434 if (relLastPullPosition <= relPos-2)
00435 {
00436
00437 undoRec.lostPos0 = todoConstPoints->at(relLastPullPosition.getValue());
00438 undoRec.lostPos1 = todoConstPoints->at(relLastPullPosition+1);
00439
00440 for (RelativeInt i(lastPullPosition, pullFront); i<=relPos-2; i++)
00441 {
00442 todoPoints->at(i.getValue()) = todoConstPoints->at(i+2);
00443 }
00444 todoPoints->at(relPos-1) = c;
00445 todoPoints->at(relPos.getValue()) = l;
00446 }
00447 else if (lastPullPosition == relPos-1)
00448 {
00449
00450 undoRec.lostPos0 = todoConstPoints->at(relPos-1);
00451 todoPoints->at(relPos-1) = c;
00452 undoRec.lostPos1 = todoConstPoints->at(relPos.getValue());
00453 todoPoints->at(relPos.getValue()) = l;
00454 }
00455 else if (lastPullPosition == relPos.getValue())
00456 {
00457
00458 undoRec.lostPos1 = todoConstPoints->at(relPos.getValue());
00459 todoPoints->at(relPos.getValue()) = l;
00460 }
00461
00462 return todo;
00463 }
00464
00465 size_t
00466 PullMoveSet::getMoveNumber(const LatticeProtein * const lp) const
00467 {
00468 assertbiu(lp!=NULL,
00469 "PullMoveSet::getMoveNumber: " <<
00470 "lp is not allowed to be NULL.");
00471 return decoder->getMoveNumber(lp->getSequence().size());
00472 }
00473
00474 LatticeProtein*
00475 PullMoveSet::undoLastMove(LatticeProtein* _toUndo)
00476 {
00477 LatticeProtein_Ipnt* toUndo =
00478 dynamic_cast<LatticeProtein_Ipnt*>(_toUndo);
00479 assertbiu(toUndo!=NULL,
00480 "PullMoveSet::undoLastMove: Downcasting to " <<
00481 "LatticeProtein_Ipnt failed.");
00482
00483 IPointVec* const toUndoPoints = toUndo->getPointsRef();
00484
00485 if (toUndo == undoRec.lastChangedObject && undoRec.hasChanged)
00486 {
00487 undoRec.hasChanged = false;
00488
00489 const RelativeInt relPos(undoRec.position, undoRec.pullFront);
00490 const RelativeInt relLastPullPos
00491 (undoRec.lastPullPosition, undoRec.pullFront);
00492 if ((int)undoRec.lastPullPosition == relPos.getValue())
00493 {
00494 toUndoPoints->at(relPos.getValue()) = undoRec.lostPos1;
00495 }
00496 if ((int)undoRec.lastPullPosition == relPos-1)
00497 {
00498 toUndoPoints->at(relPos.getValue()) = undoRec.lostPos1;
00499 toUndoPoints->at(relPos-1) = undoRec.lostPos0;
00500 }
00501 if (relLastPullPos <= relPos-2)
00502 {
00503
00504 for (RelativeInt i(undoRec.position, undoRec.pullFront);
00505 i>=relLastPullPos+2; i--)
00506 {
00507 toUndoPoints->at(i.getValue()) = toUndoPoints->at(i-2);
00508 }
00509 toUndoPoints->at(relLastPullPos.getValue()) = undoRec.lostPos0;
00510 toUndoPoints->at(relLastPullPos + 1) = undoRec.lostPos1;
00511 }
00512 }
00513
00514 return toUndo;
00515 }
00516
00517 const PullMoveSet::PullMoveDecoder* const
00518 PullMoveSet::getDecoder(void) const {
00519 return decoder;
00520 }
00521 }