Generated on Mon Jun 23 17:17:53 2008 for ell-2.3.0 by doxygen 1.5.1

src/ell/spinglass/S_SG_Ising.cc

Go to the documentation of this file.
00001 #include "ell/spinglass/S_SG_Ising.hh"
00002 #include <biu/assertbiu.hh>
00003 #include "biu/RandomNumberFactory.hh"
00004 
00005 #include <iostream>
00006 
00007 namespace ell
00008 {
00009     const biu::Alphabet S_SG_Ising::spinAlph = biu::Alphabet("-+",1);
00010     const S_SG_Ising::SpinType S_SG_Ising::SPIN_UP = S_SG_Ising::spinAlph.getElement("+");
00011     const S_SG_Ising::SpinType S_SG_Ising::SPIN_DOWN = S_SG_Ising::spinAlph.getElement("-");
00012 
00013         /* Constructs a spin array of the given size and initializes with 
00014          * SPIN_UP for all spins or a random distribution.
00015          * @param size the size of the spin array
00016          * @param random if true a random initialization is done
00017          */ 
00018     S_SG_Ising::S_SG_Ising(size_t size, bool rand)
00019      :  spin(size,SPIN_UP) 
00020     {
00021         if (rand) {
00022             for (SpinArray::iterator it = spin.begin(); it!=spin.end();it++) {
00023                 *it = ( biu::RNF::getRN(2) == 1 ? SPIN_UP : SPIN_DOWN );
00024             }
00025         }
00026     }
00027     
00028     S_SG_Ising::S_SG_Ising(const std::string & spinStr)
00029      :  spin() 
00030     {
00031         assertbiu(spinAlph.isAlphabetString(spinStr), "given spin string is no +- string");
00032         spin = spinAlph.getSequence(spinStr);
00033     }
00034     
00035     S_SG_Ising::S_SG_Ising(const S_SG_Ising& s2)
00036      : spin(s2.spin)
00037     {
00038     }
00039 
00040     S_SG_Ising::~S_SG_Ising()
00041     {
00042     }
00043 
00044     bool
00045     S_SG_Ising::operator== (const State& state2) const {
00046         return (this == &state2) || getMinimalDistance(state2) == 0;
00047     }
00048     
00049     bool
00050     S_SG_Ising::operator!= (const State& state2) const {
00051         return (this != &state2) && getMinimalDistance(state2) != 0;
00052     }
00053 
00054     void
00055     S_SG_Ising::operator= (const S_SG_Ising& sg2) {
00056         if (this == &sg2)
00057             return;
00058         spin.resize(sg2.spin.size());
00059         std::copy<SpinArray::const_iterator, SpinArray::iterator>
00060             (   sg2.spin.begin(), sg2.spin.end(), 
00061                 spin.begin());
00062     }
00063 
00064         /* Returns the negated energy of the spinglass. */
00065     int 
00066     S_SG_Ising::getFitness() const {
00067         return -(int)getEnergy();
00068     }
00069     
00070         /* Returns the state specific energy, i.e.
00071          * E = sum ( J(i,j)*spin(i)*spin(j) ) for all 0<=i<j<=spinnumber
00072          * and J(i,j) = 1 iif spin i and j are neighbored and 0 otherwise. */
00073     double  
00074     S_SG_Ising::getEnergy() const {
00075         if (spin.size() == 0)
00076             return 0;
00077         SpinType last = *spin.rbegin();
00078         int e = 0;
00079         for (SpinArray::const_iterator it = spin.begin(); it != spin.end(); it++) {
00080             e += ((*it) == last ? +1 : -1);
00081             last = *it;
00082         }
00083         return -(double)e;
00084     }
00085     
00086         /* Returns the minimal number of steps via valid
00087          *  neighbored states from this to another valid State.
00088          *  @param state2 the State to reach
00089          */
00090     unsigned int
00091     S_SG_Ising::getMinimalDistance(const State& state2) const {
00092         unsigned int minD = UINT_MAX;
00093         const S_SG_Ising* s2 = dynamic_cast<const S_SG_Ising*>(&state2);
00094         if (s2 != NULL && spin.size() == s2->spin.size()) {
00095             minD = 0;
00096             SpinArray::const_iterator is1 = spin.begin(), is2 = s2->spin.begin();
00097             while (is1 != spin.end()) {
00098                 minD += (*is1++ == *is2++ ? 0 : 1); // count different positions
00099             }
00100         }
00101         return minD;
00102     }
00103 
00104         /* Returns a pointer to a clone of the current state. */
00105     State*
00106     S_SG_Ising::clone() const {
00107         return new S_SG_Ising(*this);
00108     }
00109     
00112     State* 
00113     S_SG_Ising::fromString(const std::string& stringRep) const {
00114         return new S_SG_Ising(stringRep);
00115     }
00116     
00117         /* Returns a specific std::string representation of this
00118          *  State.
00119          */
00120     std::string 
00121     S_SG_Ising::toString() const {
00122         return spinAlph.getString(spin);
00123     }
00124 
00125     // neighborhood
00126         /* Returns a virtual list of all VALID neighbored states in
00127          *  the energy landscape in a specific order.
00128          */
00129     State::NeighborListPtr  
00130     S_SG_Ising::getNeighborList() const {
00131         return NeighborListPtr(new SuccessiveNeighborList(this));
00132     }
00133 
00134         /* Returns a virtual list of all VALID neighbored states in
00135          *  the energy landscape in a random order.
00136          *  If a state is given, this is changed to a neighbor.
00137          */
00138     State::NeighborListPtr  
00139     S_SG_Ising::getRandomNeighborList() const {
00140         return NeighborListPtr(new RandomNeighborList(this));
00141     }
00142     
00143         /* Returns a VALID random neighbored state.
00144          *  If a state is given it is overwritten and changed to a neighbor.
00145          */
00146     State* 
00147     S_SG_Ising::getRandomNeighbor(State* inPlaceNeigh) const {
00148         S_SG_Ising *s2 = NULL;
00149          // copy myself into inPlaceNeigh
00150         if (inPlaceNeigh == NULL) {
00151             s2 = new S_SG_Ising(*this);
00152             inPlaceNeigh = s2;
00153         } else {
00154             s2 = dynamic_cast<S_SG_Ising*>(inPlaceNeigh);
00155             assertbiu(s2 != NULL, "given state is no S_SG_Ising");
00156             *s2 = *this;
00157         }
00158          // get random position to flip
00159         size_t pos = biu::RNF::getRN(spin.size());
00160          // apply spin flip to pos in new state
00161         s2->spin[pos] = flipSpin(spin[pos]);
00162         
00163         return inPlaceNeigh;
00164     }
00165 
00166 
00167       // How many neighbor indices are accessible.
00168       // @return the number of neighbors
00169     size_t 
00170     S_SG_Ising::getNeighborNumber(void) const {
00171         return spin.size();
00172     }
00173     
00174       // Access to a specific neighbor.
00175       // @param index the index of the neighbor in [0, getNeighborNumber())
00176       // @param neigh if != NULL this state should be converted into the 
00177       //              neighbor
00178       // @return the new neighbor state or NULL if the index is >= 
00179       // getNeighborNumber()
00180     State* 
00181     S_SG_Ising::getNeighbor(const size_t index, State* neigh) const {
00182         assertbiu(index < spin.size(), "index out of spin range");
00183         S_SG_Ising* ret = dynamic_cast<S_SG_Ising*>(neigh);
00184         if (ret == NULL) { // create copy
00185             ret = new S_SG_Ising(*this);
00186         } else {
00187             ret->spin = this->spin;
00188         }
00189         ret->spin[index] = flipSpin(spin[index]);
00190         return ret;
00191     }
00192     
00193       // Undo the changes done to this state to generate the given neighbor.
00194       // The goal is to do less operations than doing a full copy like
00195       // (*neigh = *this).
00196       // @param index the neighbor index that was applied last 
00197       //              [ 0, getNeighborNumber() )
00198       // @param neigh the state resulting from the last changes ( != NULL)
00199       // @return the copy of this object via undoing the last changes in 
00200       //         neigh
00201     State* 
00202     S_SG_Ising::undoNeighborChange(const size_t index, State* const neigh) const {
00203         S_SG_Ising* ret = dynamic_cast<S_SG_Ising*>(neigh);
00204         assertbiu(ret != NULL, "given neigh is no S_SG_Ising object");
00205         assertbiu(index < spin.size(), "index out of spin range");
00206         ret->spin[index] = spin[index];
00207         return ret;
00208     }
00209     
00210       // Applies the necessary changes to a given state to get the neighbor.
00211       // Note: neigh is expected to be a copy (i.e. *this == *neigh) and
00212       // therefore direct changes are possible or to be NULL. If 
00213       // (neigh==NULL) a copy of this has to be generated, modified, and
00214       // returned.
00215       // @param index the neighbor to generate
00216       // @param neigh a copy of this the changes should be applied to
00217       // @return the neighbor state of the given index or NULL if the index is
00218       //         out of range
00219     State* 
00220     S_SG_Ising::applyNeighborChange(const size_t index, State* const neigh) const {
00221         assertbiu(index < spin.size(), "index out of spin range");
00222         assertbiu(neigh != NULL, "no state to fill given");
00223         S_SG_Ising* ret = dynamic_cast<S_SG_Ising*>(neigh);
00224         assertbiu(ret != NULL, "given neigh is no S_SG_Ising object");
00225         ret->spin[index] = flipSpin(spin[index]);
00226         return ret;
00227     }
00228     
00229 
00231     
00232         /* Access to a compressed sequence representation of the state.
00233          * @return the compressed sequence representation
00234          */
00235     CSequence  
00236     S_SG_Ising::compress(void) const {
00237         return spinAlph.compress(spin);
00238     }
00239     
00240         /* Access to a compressed sequence representation of the state.
00241          * @param toFill a data structure to write the compressed 
00242          *               representation too
00243          * @return the compressed sequence representation
00244          */
00245     CSequence&  
00246     S_SG_Ising::compress(CSequence& toFill) const {
00247         toFill = spinAlph.compress(spin);
00248         return toFill;
00249     }
00250     
00251         /* Uncompresses a compressed sequencce representation into a new
00252          * State object.
00253          * @param cseq the compressed sequence representation of a state
00254          * @param toFill a state object to uncompress too or NULL if a new 
00255          *               object has to be created
00256          * @return new State object that is encoded in cseq or NULL in error
00257          *         case.
00258          */
00259     State*  
00260     S_SG_Ising::uncompress(const CSequence& cseq, State* toFill) const {
00261         S_SG_Ising* sgi = dynamic_cast<S_SG_Ising*>(toFill);
00262         if (sgi == NULL) {
00263             if (toFill != NULL)
00264                 delete toFill;
00265             sgi = new S_SG_Ising(*this);
00266             toFill = sgi;
00267         }
00268         sgi->spin = spinAlph.decompress(cseq, spin.size()); 
00269         return toFill;
00270     }
00271     
00272         /* Uncompresses a compressed sequencce representation into a this
00273          * State object.
00274          * @param cseq the compressed sequence representation of a state
00275          * @return this or NULL in error case
00276          */
00277     State*  
00278     S_SG_Ising::uncompress(const CSequence& cseq) {
00279         spin = spinAlph.decompress(cseq, spin.size());
00280         return this;
00281     }
00282     
00283 } // namespace