Generated on Mon Jun 23 16:24:56 2008 for BIU-1.7.0 by doxygen 1.5.1

src/biu/PullMoveSet.cc

Go to the documentation of this file.
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         // save all neighbor vectors for reference
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         // set up stdPulls
00021         // structure: direction i->(x) : pull number : (c, l)
00022         
00023         // for every direction between two neighbors
00024         for (LatticeNeighborhood::const_iterator direction = neighbors.begin();
00025                 direction != neighbors.end(); direction++)
00026         {
00027             std::vector< std::vector< IntPoint > > stdMoves;
00028             // for each neighbor of i
00029             for (LatticeNeighborhood::const_iterator nbi = neighbors.begin();
00030                     nbi != neighbors.end(); nbi++)
00031             {
00032                 // for each neighbor of (x)
00033                 if (*nbi != *direction)
00034                 for (LatticeNeighborhood::const_iterator nb = neighbors.begin();
00035                 nb != neighbors.end(); nb++)
00036                 {
00037                     // if neighbor of i and neighbor of (x) are neighbored
00038                     // save new c,l pair
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         // set up endPulls
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         // code table:
00079         // *********************************
00080         // legal moves: 
00081         //      [0, endPullNumber*2 + (proteinLength-1)*stdPullNumber*2 - 1]
00082         // end pulls @ position 0:
00083         //      [endPullNumber, 2*endPullNumber - 1]
00084         // end pulls @ last position:
00085         //      [0, endPullNumber - 1]
00086         // standart pulls:
00087         //      [2*endPullNumber, 
00088         //          endPullNumber*2 + (proteinLength-1)*stdPullNumber*2 - 1]
00089         
00090         if (moveIndex < endPullNumber) 
00091         {
00092             // end pull at end position
00093             pullFront=true;
00094             stdPull=false;
00095             movePosition=todoSize-1;
00096             return;
00097         }
00098         else if (moveIndex < endPullNumber*2)
00099         {
00100             // end pull at position 0
00101             pullFront=false;
00102             stdPull=false;
00103             movePosition=0;
00104             moveIndex-=endPullNumber;
00105             return;
00106         }
00107         else
00108         {
00109             // do std pulls
00110             stdPull = true;
00111             moveIndex -= endPullNumber*2;
00112             if (moveIndex < stdPullNumber)
00113             {
00114                 // pull first element & pull front
00115                 pullFront = true;
00116                 movePosition = 0;
00117                 return;
00118             }
00119             else if (moveIndex < stdPullNumber*2)
00120             {
00121                 // pull last element & pull back
00122                 moveIndex -= stdPullNumber;
00123                 pullFront = false;
00124                 movePosition = todoSize-1;
00125                 return;
00126             }
00127             else
00128             {
00129                 // do standard pull @ element in [1, todoSize-1]
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             // check where to look in stdPulls
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 +                           // # of end pulls
00173                 (proteinLength-1)*stdPullNumber*2;          // # of std pulls
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         // apply the pivot move inplace to a copy of todo
00244         LatticeProtein_Ipnt* l = new LatticeProtein_Ipnt(*todo);
00245         LatticeProtein* l2 = applyMoveInPlace(l, moveIndex);
00246         
00247         // delete l2 if we don't need it!
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         // lookup PullFront, stdPull and the pull position
00272         bool pullFront;
00273         bool stdPull;
00274         size_t position;
00275         decoder->lookupMove(todoSize, moveIndex, pullFront, stdPull, position);
00276         
00277         // RelativeInt objects are used to be able to compute both pull 
00278         // directions the same code
00279         const RelativeInt relPos(position, pullFront);
00280         const RelativeInt relLastElement((pullFront ? 0 : todoSize-1), pullFront);
00281         
00282         // const pointer to const reference to lattice protein IPoints
00283         const IPointVec* const todoConstPoints = todo->getPointsRef();
00284         // pointer to mutable LatticeProtein IPoints
00285         IPointVec* const todoPoints = todo->getPointsRef();
00286         
00287         // do end pull
00288         if (!stdPull) 
00289         {
00290             IPointVec pullPoints = 
00291                 decoder->lookupEndMove(todoConstPoints->at(position), 
00292                                         moveIndex);
00293             
00294             // move legal? -> pull positions not occupied
00295             for (IPointVec::const_iterator it = todoConstPoints->begin(); 
00296                     it != todoConstPoints->end(); it++)
00297             {
00298                 // if position occupied, leave
00299                 if ( (*it == pullPoints.at(0)) || (*it == pullPoints.at(1)) ) 
00300                     return NULL;
00301             }
00302             
00303             // save undo information
00304             undoRec.hasChanged = true;
00305             undoRec.lastChangedObject = todo;
00306             undoRec.position = position;
00307             undoRec.pullFront = pullFront;
00308             
00309             // check how far to pull
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(); // default
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             // pull tail
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         // look up pullPoint & fixedPoint
00344         const IntPoint pullPoint = todoConstPoints->at(position);
00345         const IntPoint fixedPoint = todoConstPoints->at(relPos + 1);
00346                 
00347         // look up c & l
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         // check if C and L are valid positions
00354         // if C position occupied by element in pull direction
00355         // or if moving first element while pulling front
00356         // or if moving last element while pulling back
00357         if ( (pullFront && position == 0) 
00358                 || (!pullFront && position == todoSize-1) 
00359                 || (c==todoConstPoints->at(relPos - 1)) )
00360         // just check for L position
00361         {
00362             for (IPointVec::const_iterator it = todoConstPoints->begin(); 
00363                 it != todoConstPoints->end(); it++)
00364             {
00365                 // if L position occupied, leave
00366                 if ((*it) == l) return NULL;
00367             }
00368         }
00369         // check both C and L positions
00370         else
00371         {
00372             for (IPointVec::const_iterator it = todoConstPoints->begin(); 
00373             it != todoConstPoints->end(); it++)
00374             {
00375                 // if C or L position occupied, leave
00376                 if (((*it) == l) || ((*it) == c)) return NULL;
00377             }
00378         }
00379 
00380         // compute how much needs to be moved
00381         int lastPullPosition=-1;                    // last element to be moved
00382         bool lastPullPositionFound = false;
00383 
00384         // if moving first element while pulling front
00385         // or if moving last element while pulling back
00386         // or if moving second element
00387         if (relPos <= relLastElement + 1)
00388         {
00389             lastPullPosition = relLastElement.getValue();
00390             lastPullPositionFound = true;
00391         }
00392         // if moving anything above second element
00393         else
00394         {
00395             // if c and position-2 are neighbored
00396             if (lattice->areNeighbored(c, todoConstPoints->at(relPos-2)))
00397             {
00398                 // just change position and position-1
00399                 lastPullPosition = relPos-1;
00400                 lastPullPositionFound = true;
00401             }
00402         }
00403         // if moving anything above third element
00404         if (relPos >= relLastElement + 3
00405                 && !lastPullPositionFound)
00406         {
00407             // check beyond position-2
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                     // pull until position i-2
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         // save values for undo:
00426         undoRec.lastChangedObject = todo;
00427         undoRec.hasChanged = true;
00428         undoRec.pullFront = pullFront;
00429         undoRec.position = position;
00430         undoRec.lastPullPosition = lastPullPosition;
00431         
00432         // move
00433         const RelativeInt relLastPullPosition(lastPullPosition, pullFront);
00434         if (relLastPullPosition <= relPos-2)
00435         {
00436             // save for undo
00437             undoRec.lostPos0 = todoConstPoints->at(relLastPullPosition.getValue());
00438             undoRec.lostPos1 = todoConstPoints->at(relLastPullPosition+1);
00439             // pull tail if existent
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             // save for undo
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             // save for undo
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                 // undo pulling whole tail
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 }