- Modify MaxChangeScoreState to use the list macros.
- Clean up various attempts at automatically picking parameters in the nonbonded lists. For now just have them be user setable.
Also, I don't think that functions which are not part of the API should be given doxygen comments.
Index: kernel/include/IMP/score_states/MaxChangeScoreState.h =================================================================== --- kernel/include/IMP/score_states/MaxChangeScoreState.h (revision 560) +++ kernel/include/IMP/score_states/MaxChangeScoreState.h (working copy) @@ -27,9 +27,7 @@ { FloatKeys keys_; FloatKeys origkeys_; - Particles ps_; float max_change_; - virtual void do_before_evaluate(); public: //! Track the changes with the specified keys. MaxChangeScoreState(const FloatKeys &keys, @@ -37,6 +35,8 @@
virtual ~MaxChangeScoreState(){}
+ IMP_SCORE_STATE(internal::kernel_version_info); + //! Measure differences from the current value. void reset();
Index: kernel/src/score_states/MaxChangeScoreState.cpp =================================================================== --- kernel/src/score_states/MaxChangeScoreState.cpp (revision 560) +++ kernel/src/score_states/MaxChangeScoreState.cpp (working copy) @@ -74,4 +74,8 @@ max_change_=0; }
+void MaxChangeScoreState::show(std::ostream &out) const { + out << "MaxChangeScoreState" << std::endl; +} + } // namespace IMP
Index: kernel/include/IMP/score_states/NonbondedListScoreState.h =================================================================== --- kernel/include/IMP/score_states/NonbondedListScoreState.h (revision 560) +++ kernel/include/IMP/score_states/NonbondedListScoreState.h (working copy) @@ -42,15 +42,19 @@ /** How much to add to the size of particles to allow particles to move without rebuilding the list */ Float slack_; - //! An estimate of what the slack should be next time the list is recomputed - Float next_slack_; - int num_steps_; bool nbl_is_valid_; int number_of_rebuilds_; int number_of_updates_; + int number_of_overflows_; + //! The maximum allowable size for the NBL + /** An exception will be thrown if the list exceeds this size. + */ + unsigned int max_nbl_size_; typedef std::vector<std::pair<Particle*, Particle*> > NBL; NBL nbl_;
+ struct NBLTooLargeException{}; + protected:
Float get_slack() const {return slack_;} @@ -93,7 +97,11 @@ if (!are_bonded(a,b)) { IMP_LOG(VERBOSE, "Found pair " << a->get_index() << " " << b->get_index() << std::endl); - nbl_.push_back(std::make_pair(a, b)); + if (nbl_.size() < max_nbl_size_) { + nbl_.push_back(std::make_pair(a, b)); + } else { + throw NBLTooLargeException(); + } } else { IMP_LOG(VERBOSE, "Pair " << a->get_index() << " and " << b->get_index() << " rejected on bond" @@ -184,6 +192,29 @@ FloatKey get_radius_key() const {return rk_;} void set_radius_key(FloatKey rk) {rk_=rk;}
+ //! Set the maximum allowable size for the NBL + /** The NBL will keep reducing the slack and trying to + rebuild until it can make the list smaller than this. + */ + void set_max_size(unsigned int mx) { + max_nbl_size_= mx; + } + + + //! Set the slack used when generating the NBL + /** The slack allows the the NBL to non be rebuilt every step + making the process more efficient. However, too large + a value can result in the NBL being excessively large. + + A good guideline is that it should be the maximum amount + a particle coordinate would change in 20 steps or so. + */ + void set_slack(float slack) { + IMP_check(slack>= 0, "Slack must be nonnegative", + ValueException("Negative slack")); + slack_=slack; + } + IMP_CONTAINER(BondedListScoreState, bonded_list, BondedListIndex);
Index: kernel/src/score_states/NonbondedListScoreState.cpp =================================================================== --- kernel/src/score_states/NonbondedListScoreState.cpp (revision 560) +++ kernel/src/score_states/NonbondedListScoreState.cpp (working copy) @@ -37,11 +37,11 @@ cutoff_(cut), nbl_is_valid_(false) { - slack_=20; - next_slack_=slack_; - num_steps_=1; + slack_=cutoff_; number_of_updates_=1; number_of_rebuilds_=0; + number_of_overflows_=0; + max_nbl_size_= std::numeric_limits<unsigned int>::max(); }
@@ -55,7 +55,9 @@ { out << "Nonbonded list averaged " << static_cast<Float>(number_of_updates_) - / number_of_rebuilds_ << " steps between rebuilds" << std::endl; + / number_of_rebuilds_ << " steps between rebuilds" + << " and overflowed " << number_of_overflows_ + << " times" << std::endl; }
@@ -96,47 +98,25 @@ (*bli)->before_evaluate(ScoreState::get_before_evaluate_iteration()); }
- if (nbl_is_valid_) { - /*std::cout << "Rate is " << rate << " target is " << target_steps - << " so slack is " << target_slack << " mc " << mc - << " nbl " << nbl_.size() << " cost " - << rebuild_cost << std::endl;*/ - if (mc > slack_) { - /* Float rate= std::pow(static_cast<Float>(nbl_.size()), - .333f)/ num_steps_; - Float target_steps= .6*std::pow(rebuild_cost, .25f) - *std::pow(rate, -.75f); - Float target_slack= (target_steps+1)*mc/num_steps_; - next_slack_= target_slack*.5 + .5*next_slack_; - */ - - /*std::cout << "Killing nbl because " << mc << " - << slack_ << " " << next_slack_ - << " " << num_steps_ << std::endl;*/ - if (num_steps_ < 50) { - //slack_= next_slack_; - } - num_steps_=1; - //next_slack_= std::max(2.0*mc, 2.0*slack_); - set_nbl_is_valid(false); - ++number_of_rebuilds_; - slack_=next_slack_; - /*} else if (num_steps_ > 100) { - //next_slack_=slack_/2.0; - slack_=next_slack_; - num_steps_=1; - set_nbl_is_valid(false); - ++number_of_rebuilds_;*/ - } else { - ++num_steps_; - //next_slack_= next_slack_*.98; - } - } - bool rebuilt=false; if (!get_nbl_is_valid()) { - rebuild_nbl(); - rebuilt=true; + unsigned int rebuild_attempts=0; + do { + try { + ++rebuild_attempts; + ++number_of_rebuilds_; + rebuild_nbl(); + rebuilt=true; + } catch (NBLTooLargeException &) { + slack_= slack_/2.0; + ++number_of_overflows_; + if (number_of_rebuilds_==100) { + IMP_WARN("Can't rebuild NBL with given max NBL size of " + << max_nbl_size_ << std::endl); + throw ValueException("Bad NBL max size"); + } + } + } while (!rebuilt); } else { nbl_.erase(std::remove_if(nbl_.begin(), nbl_.end(), internal::HasInactive()),
Daniel Russel wrote: > - Clean up various attempts at automatically picking parameters in the > nonbonded lists. For now just have them be user setable.
With this patch, 'scons examples' always fails for me on synth, with errors like:
scons: Building targets ... builder_unit_test(["kernel/doc/examples/examples.passed"], ["bin/imppy.sh", "kernel/doc/examples/chain.py"]) cd /synth1/home/ben/imp/kernel/doc/examples && /synth1/home/ben/imp/bin/imppy.sh python chain.py > /dev/null ERROR: Nonbonded list is missing (7) (5.34008, 3.38164, 5.22317) 1 and (1) (7.81002, 2.4397, 4.51924)1 size is 75
> Also, I don't think that functions which are not part of the API should > be given doxygen comments.
Didn't we have this discussion already? I prefer to mark such functions as \internal. That makes it obvious that it's internal, not that you just forgot to doxygenize your comments. And some users like the doxygen indexing and interface to browse their internal functions too - they have the option this way to just ask doxygen to include \internal functions. They can't do that if such functions have non-doxygen comments.
Ben
> > Didn't we have this discussion already? I prefer to mark such > functions as \internal. That makes it obvious that it's internal, not > that you just forgot to doxygenize your comments. And some users like > the doxygen indexing and interface to browse their internal functions > too - they have the option this way to just ask doxygen to include > \internal functions. They can't do that if such functions have > non-doxygen comments. Sure, then if you change the comments to doxygen ones, mark them as internal :-)
Ben Webb wrote: > Daniel Russel wrote: >> - Clean up various attempts at automatically picking parameters in >> the nonbonded lists. For now just have them be user setable. > > With this patch, 'scons examples' always fails for me on synth, with > errors like: > > scons: Building targets ... > builder_unit_test(["kernel/doc/examples/examples.passed"], > ["bin/imppy.sh", "kernel/doc/examples/chain.py"]) > cd /synth1/home/ben/imp/kernel/doc/examples && > /synth1/home/ben/imp/bin/imppy.sh python chain.py > /dev/null > ERROR: Nonbonded list is missing (7) (5.34008, 3.38164, 5.22317) 1 and > (1) (7.81002, 2.4397, 4.51924)1 size is 75 That was dumb. In cleaning it up for submit I disabled rebuilding of nbl. Oops. Strange that it didn't get triggered on my machine.
Here is an improved patch
While I am at it, here is a patch which moves the "-O3" flag for gcc to being controlled by the release flag as it makes non release building take a really long time and be hard to debug.
Finally, I cleaned up the example slightly
Index: kernel/include/IMP/score_states/NonbondedListScoreState.h =================================================================== --- kernel/include/IMP/score_states/NonbondedListScoreState.h (revision 561) +++ kernel/include/IMP/score_states/NonbondedListScoreState.h (working copy) @@ -42,15 +42,18 @@ /** How much to add to the size of particles to allow particles to move without rebuilding the list */ Float slack_; - //! An estimate of what the slack should be next time the list is recomputed - Float next_slack_; - int num_steps_; bool nbl_is_valid_; int number_of_rebuilds_; int number_of_updates_; - typedef std::vector<std::pair<Particle*, Particle*> > NBL; - NBL nbl_; + int number_of_overflows_; + //! The maximum allowable size for the NBL + /** An exception will be thrown if the list exceeds this size. + */ + unsigned int max_nbl_size_; + ParticlePairs nbl_;
+ struct NBLTooLargeException{}; + protected:
Float get_slack() const {return slack_;} @@ -93,7 +96,11 @@ if (!are_bonded(a,b)) { IMP_LOG(VERBOSE, "Found pair " << a->get_index() << " " << b->get_index() << std::endl); - nbl_.push_back(std::make_pair(a, b)); + if (nbl_.size() < max_nbl_size_) { + nbl_.push_back(std::make_pair(a, b)); + } else { + throw NBLTooLargeException(); + } } else { IMP_LOG(VERBOSE, "Pair " << a->get_index() << " and " << b->get_index() << " rejected on bond" @@ -184,6 +191,29 @@ FloatKey get_radius_key() const {return rk_;} void set_radius_key(FloatKey rk) {rk_=rk;}
+ //! Set the maximum allowable size for the NBL + /** The NBL will keep reducing the slack and trying to + rebuild until it can make the list smaller than this. + */ + void set_max_size(unsigned int mx) { + max_nbl_size_= mx; + } + + + //! Set the slack used when generating the NBL + /** The slack allows the the NBL to non be rebuilt every step + making the process more efficient. However, too large + a value can result in the NBL being excessively large. + + A good guideline is that it should be the maximum amount + a particle coordinate would change in 20 steps or so. + */ + void set_slack(float slack) { + IMP_check(slack>= 0, "Slack must be nonnegative", + ValueException("Negative slack")); + slack_=slack; + } + IMP_CONTAINER(BondedListScoreState, bonded_list, BondedListIndex);
@@ -201,7 +231,7 @@ /** The value type is an ParticlePair. */ typedef boost::filter_iterator<BoxesOverlap, - NBL::const_iterator> NonbondedIterator; + ParticlePairs::const_iterator> NonbondedIterator;
//! Iterates through the pairs of non-bonded particles NonbondedIterator nonbonded_begin() const { @@ -217,6 +247,9 @@ nbl_.end(), nbl_.end()); }
+ const ParticlePairs get_nonbonded() const { + return nbl_; + }
unsigned int number_of_nonbonded() const { IMP_check(get_nbl_is_valid(), "Must call update first", Index: kernel/src/score_states/NonbondedListScoreState.cpp =================================================================== --- kernel/src/score_states/NonbondedListScoreState.cpp (revision 561) +++ kernel/src/score_states/NonbondedListScoreState.cpp (working copy) @@ -37,11 +37,11 @@ cutoff_(cut), nbl_is_valid_(false) { - slack_=20; - next_slack_=slack_; - num_steps_=1; + slack_=cutoff_; number_of_updates_=1; number_of_rebuilds_=0; + number_of_overflows_=0; + max_nbl_size_= std::numeric_limits<unsigned int>::max(); }
@@ -55,7 +55,9 @@ { out << "Nonbonded list averaged " << static_cast<Float>(number_of_updates_) - / number_of_rebuilds_ << " steps between rebuilds" << std::endl; + / number_of_rebuilds_ << " steps between rebuilds" + << " and overflowed " << number_of_overflows_ + << " times" << std::endl; }
@@ -96,47 +98,26 @@ (*bli)->before_evaluate(ScoreState::get_before_evaluate_iteration()); }
- if (nbl_is_valid_) { - /*std::cout << "Rate is " << rate << " target is " << target_steps - << " so slack is " << target_slack << " mc " << mc - << " nbl " << nbl_.size() << " cost " - << rebuild_cost << std::endl;*/ - if (mc > slack_) { - /* Float rate= std::pow(static_cast<Float>(nbl_.size()), - .333f)/ num_steps_; - Float target_steps= .6*std::pow(rebuild_cost, .25f) - *std::pow(rate, -.75f); - Float target_slack= (target_steps+1)*mc/num_steps_; - next_slack_= target_slack*.5 + .5*next_slack_; - */ - - /*std::cout << "Killing nbl because " << mc << " - << slack_ << " " << next_slack_ - << " " << num_steps_ << std::endl;*/ - if (num_steps_ < 50) { - //slack_= next_slack_; - } - num_steps_=1; - //next_slack_= std::max(2.0*mc, 2.0*slack_); - set_nbl_is_valid(false); - ++number_of_rebuilds_; - slack_=next_slack_; - /*} else if (num_steps_ > 100) { - //next_slack_=slack_/2.0; - slack_=next_slack_; - num_steps_=1; - set_nbl_is_valid(false); - ++number_of_rebuilds_;*/ - } else { - ++num_steps_; - //next_slack_= next_slack_*.98; - } - } - bool rebuilt=false; - if (!get_nbl_is_valid()) { - rebuild_nbl(); - rebuilt=true; + if (mc > slack_ || !get_nbl_is_valid()) { + unsigned int rebuild_attempts=0; + do { + try { + ++rebuild_attempts; + ++number_of_rebuilds_; + set_nbl_is_valid(false); + rebuild_nbl(); + rebuilt=true; + } catch (NBLTooLargeException &) { + slack_= slack_/2.0; + ++number_of_overflows_; + if (number_of_rebuilds_==100) { + IMP_WARN("Can't rebuild NBL with given max NBL size of " + << max_nbl_size_ << std::endl); + throw ValueException("Bad NBL max size"); + } + } + } while (!rebuilt); } else { nbl_.erase(std::remove_if(nbl_.begin(), nbl_.end(), internal::HasInactive()), @@ -154,7 +135,7 @@ { nbl_is_valid_= tf; if (!nbl_is_valid_) { - NBL empty; + ParticlePairs empty; // free memory to make sure it shrinks std::swap(empty, nbl_); } Index: kernel/src/score_states/AllNonbondedListScoreState.cpp =================================================================== --- kernel/src/score_states/AllNonbondedListScoreState.cpp (revision 561) +++ kernel/src/score_states/AllNonbondedListScoreState.cpp (working copy) @@ -94,6 +94,7 @@ } if (P::update(mc, cost)) { mc_->reset(); + mcr_->reset(); } IMP_IF_CHECK(EXPENSIVE) { check_nbl(); @@ -334,7 +335,9 @@ << " " << gr(ps[i]) << " and " << ps[j]->get_index() << " " << dj << gr(ps[j]) - << " size is " << number_of_nonbonded() << std::endl); + << " size is " << number_of_nonbonded() + << " distance is " << distance(di, dj) + << " max is " << mc_->get_max() << std::endl); } } }
Index: tools/__init__.py =================================================================== --- tools/__init__.py (revision 561) +++ tools/__init__.py (working copy) @@ -53,7 +53,9 @@ def _add_release_flags(env): """Add compiler flags for release builds, if requested""" if env.get('release', False): - env.Append(CPPDEFINES='NDEBUG') + env.Append(CPPDEFINES=['NDEBUG']) + if env['CC'] == 'gcc': + env.Append(CCFLAGS=['-O3'])
def CheckGNUHash(context): """Disable GNU_HASH-style linking (if found) for backwards compatibility""" @@ -186,7 +188,7 @@ pass env.Prepend(SCANNERS = _SWIGScanner) if env['CC'] == 'gcc': - env.Append(CCFLAGS="-Wall -g -O3") + env.Append(CCFLAGS="-Wall -g") if env.get('include', None) is not None: env['include'] = [os.path.abspath(x) for x in \ env['include'].split(os.path.pathsep)]
Index: kernel/doc/examples/chain.py =================================================================== --- kernel/doc/examples/chain.py (revision 561) +++ kernel/doc/examples/chain.py (working copy) @@ -7,27 +7,28 @@ # another.
#IMP.set_log_level(IMP.VERBOSE) +np=20 radius =1.0 rk= IMP.FloatKey("radius") m= IMP.Model() # The particles in the chain chain= IMP.Particles() -for i in range(0,20): +for i in range(0,np): p= IMP.Particle() pi= m.add_particle(p) d= IMP.XYZDecorator.create(p) - d.set_x(random.uniform(0,10)) - d.set_y(random.uniform(0,10)) - d.set_z(random.uniform(0,10)) + d.randomize_in_box(IMP.Vector3D(0,0,0), + IMP.Vector3D(10,10,10)) d.set_coordinates_are_optimized(True) p.add_attribute(rk, radius, False) - # create a bond between successive particles - if (i != 0): - bp= IMP.BondedDecorator.create(p) - bpr= IMP.BondedDecorator.cast(chain.back()) - b= IMP.custom_bond(bp, bpr, 1.5*radius, 10) chain.append(p)
+# create a bond between successive particles +for i in range(1, len(chain)): + bp= IMP.BondedDecorator.create(chain[i]) + bpr= IMP.BondedDecorator.cast(chain[i-1]) + b= IMP.custom_bond(bp, bpr, 1.5*radius, 10) + # If you want to inspect the particles # Notice that each bond is a particle for p in m.get_particles():
participants (2)
-
Ben Webb
-
Daniel Russel