Here is the patch that was discussed a while ago which makes UnaryFunction::evaluate_with_derivative return a std::pair instead of using one pass by reference to return. It also removes the hack in IMP.i to get the return value right.
Index: kernel/include/IMP/UnaryFunction.h =================================================================== --- kernel/include/IMP/UnaryFunction.h (revision 669) +++ kernel/include/IMP/UnaryFunction.h (working copy) @@ -14,9 +14,13 @@ namespace IMP {
+typedef std::pair<Float, Float> FloatPair; + //! Abstract single variable functor class for score functions. /** These functors take a single feature value, and return a corresponding score (and optionally also the first derivative). + + \ingroup kernel */ class IMPDLLEXPORT UnaryFunction : public RefCountedObject { @@ -36,7 +40,7 @@ given feaure. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const = 0; + virtual FloatPair evaluate_with_derivative(Float feature) const = 0;
virtual void show(std::ostream &out=std::cout) const = 0; }; Index: kernel/include/IMP/optimizers/MonteCarlo.h =================================================================== --- kernel/include/IMP/optimizers/MonteCarlo.h (revision 669) +++ kernel/include/IMP/optimizers/MonteCarlo.h (working copy) @@ -15,8 +15,6 @@ namespace IMP {
-typedef std::vector<Mover*> Movers; - //! A Monte Carlo optimizer. /** The optimizer uses a set of Mover objects to propose steps. Currently each Mover is called at each Monte Carlo iteration. This may change in Index: kernel/include/IMP/optimizers/Mover.h =================================================================== --- kernel/include/IMP/optimizers/Mover.h (revision 669) +++ kernel/include/IMP/optimizers/Mover.h (working copy) @@ -76,6 +76,8 @@
IMP_OUTPUT_OPERATOR(Mover);
+typedef std::vector<Mover*> Movers; + } // namespace IMP
#endif /* __IMP_MOVER_H */ Index: kernel/include/IMP/internal/evaluate_distance_pair_score.h =================================================================== --- kernel/include/IMP/internal/evaluate_distance_pair_score.h (revision 669) +++ kernel/include/IMP/internal/evaluate_distance_pair_score.h (working copy) @@ -9,6 +9,7 @@ #define __IMP_EVALUATE_DISTANCE_PAIR_SCORE_H
#include "../Vector3D.h" +#include <boost/tuple/tuple.hpp>
namespace IMP { @@ -43,7 +44,7 @@ if (da && distance >= MIN_DISTANCE) { Float deriv;
- score = f->evaluate_with_derivative(shifted_distance, deriv); + boost::tie(score, deriv) = f->evaluate_with_derivative(shifted_distance);
Vector3D d= delta/distance *deriv; d0.add_to_coordinates_derivative(d, *da); Index: kernel/include/IMP/unary_functions/ClosedCubicSpline.h =================================================================== --- kernel/include/IMP/unary_functions/ClosedCubicSpline.h (revision 669) +++ kernel/include/IMP/unary_functions/ClosedCubicSpline.h (working copy) @@ -40,12 +40,10 @@
//! Calculate score and derivative with respect to the given feature. /** \param[in] feature Value of feature being tested. - \param[out] deriv Partial derivative of the score with respect to - the feature value. \exception ValueException Feature is out of defined range. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const; + virtual FloatPair evaluate_with_derivative(Float feature) const;
void show(std::ostream &out=std::cout) const { out << "Closed cubic spline of " << values_.size() << " values from " Index: kernel/include/IMP/unary_functions/Linear.h =================================================================== --- kernel/include/IMP/unary_functions/Linear.h (revision 669) +++ kernel/include/IMP/unary_functions/Linear.h (working copy) @@ -28,9 +28,8 @@ return (feature-offset_)*slope_; }
- virtual Float evaluate_with_derivative(Float feature, Float& deriv) const { - deriv= slope_; - return evaluate(feature); + virtual FloatPair evaluate_with_derivative(Float feature) const { + return std::make_pair(evaluate(feature), slope_); }
void set_slope(Float f) { Index: kernel/include/IMP/unary_functions/WormLikeChain.h =================================================================== --- kernel/include/IMP/unary_functions/WormLikeChain.h (revision 669) +++ kernel/include/IMP/unary_functions/WormLikeChain.h (working copy) @@ -62,10 +62,8 @@
//! Calculate the WormLikeChain energy given the length /** \param[in] l Current length in angstroms - \param[out] deriv force in kcal/angstrom mol - \return Score */ - virtual Float evaluate_with_derivative(Float fl, Float& deriv) const { + virtual FloatPair evaluate_with_derivative(Float fl) const { unit::Angstrom l(fl); if (l < unit::Angstrom(0)) l=unit::Angstrom(0); unit::Piconewton doubled; @@ -81,9 +79,9 @@ // convert from picoNewton unit::YoctoKilocaloriePerAngstrom du= unit::convert_J_to_Cal(doubled);
- deriv = (du*unit::ATOMS_PER_MOL).get_value(); + Float deriv = (du*unit::ATOMS_PER_MOL).get_value(); //std::cout << "Which converts to " << d << std::endl; - return evaluate(fl); + return std::make_pair(evaluate(fl), deriv); }
void show(std::ostream &out=std::cout) const { Index: kernel/include/IMP/unary_functions/Cosine.h =================================================================== --- kernel/include/IMP/unary_functions/Cosine.h (revision 669) +++ kernel/include/IMP/unary_functions/Cosine.h (working copy) @@ -43,11 +43,9 @@
//! Calculate score and derivative with respect to the given feature. /** \param[in] feature Value of feature being tested. - \param[out] deriv Partial derivative of the score with respect to - the feature value. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const; + virtual FloatPair evaluate_with_derivative(Float feature) const;
void show(std::ostream &out=std::cout) const { out << "Cosine function with force " << force_constant_ Index: kernel/include/IMP/unary_functions/Harmonic.h =================================================================== --- kernel/include/IMP/unary_functions/Harmonic.h (revision 669) +++ kernel/include/IMP/unary_functions/Harmonic.h (working copy) @@ -56,20 +56,17 @@ \return Score */ virtual Float evaluate(Float feature) const { - Float d; - return evaluate_with_derivative(feature, d); + return evaluate_with_derivative(feature).first; }
//! Calculate harmonic score and derivative with respect to the given feature. /** \param[in] feature Value of feature being tested. - \param[out] deriv Partial derivative of the score with respect to - the feature value. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const { + virtual FloatPair evaluate_with_derivative(Float feature) const { Float e = (feature - mean_); - deriv = k_ * e; - return 0.5 * k_ * e * e; + Float deriv = k_ * e; + return std::make_pair(0.5 * k_ * e * e, deriv); }
void show(std::ostream &out=std::cout) const { Index: kernel/include/IMP/unary_functions/HarmonicLowerBound.h =================================================================== --- kernel/include/IMP/unary_functions/HarmonicLowerBound.h (revision 669) +++ kernel/include/IMP/unary_functions/HarmonicLowerBound.h (working copy) @@ -37,16 +37,13 @@ //! Calculate lower-bound harmonic score and derivative for a feature. /** If the feature is greater than or equal to the mean, the score is zero. \param[in] feature Value of feature being tested. - \param[out] deriv Partial derivative of the score with respect to - the feature value. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const { + virtual FloatPair evaluate_with_derivative(Float feature) const { if (feature >= Harmonic::get_mean()) { - deriv = 0.0; - return 0.0; + return std::make_pair(0.0f, 0.0f); } else { - return Harmonic::evaluate_with_derivative(feature, deriv); + return Harmonic::evaluate_with_derivative(feature); } }
Index: kernel/include/IMP/unary_functions/OpenCubicSpline.h =================================================================== --- kernel/include/IMP/unary_functions/OpenCubicSpline.h (revision 669) +++ kernel/include/IMP/unary_functions/OpenCubicSpline.h (working copy) @@ -25,7 +25,7 @@ \param[in] minrange Feature value at first spline point \param[in] spacing Distance (in feature space) between points */ - OpenCubicSpline(const std::vector<Float> &values, Float minrange, + OpenCubicSpline(const Floats &values, Float minrange, Float spacing);
virtual ~OpenCubicSpline() {} @@ -39,12 +39,10 @@
//! Calculate score and derivative with respect to the given feature. /** \param[in] feature Value of feature being tested. - \param[out] deriv Partial derivative of the score with respect to - the feature value. \exception ValueException Feature is out of defined range. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const; + virtual FloatPair evaluate_with_derivative(Float feature) const;
void show(std::ostream &out=std::cout) const { out << "Open cubic spline of " << values_.size() << " values from " Index: kernel/include/IMP/unary_functions/HarmonicUpperBound.h =================================================================== --- kernel/include/IMP/unary_functions/HarmonicUpperBound.h (revision 669) +++ kernel/include/IMP/unary_functions/HarmonicUpperBound.h (working copy) @@ -37,16 +37,13 @@ //! Calculate upper-bound harmonic score and derivative for a feature. /** If the feature is less than or equal to the mean, the score is zero. \param[in] feature Value of feature being tested. - \param[out] deriv Partial derivative of the score with respect to - the feature value. \return Score */ - virtual Float evaluate_with_derivative(Float feature, Float& deriv) const { + virtual FloatPair evaluate_with_derivative(Float feature) const { if (feature <= Harmonic::get_mean()) { - deriv = 0.0; - return 0.0; + return std::make_pair(0.0f, 0.0f); } else { - return Harmonic::evaluate_with_derivative(feature, deriv); + return Harmonic::evaluate_with_derivative(feature); } }
Index: kernel/src/singleton_scores/AttributeSingletonScore.cpp =================================================================== --- kernel/src/singleton_scores/AttributeSingletonScore.cpp (revision 669) +++ kernel/src/singleton_scores/AttributeSingletonScore.cpp (working copy) @@ -8,7 +8,7 @@ #include "IMP/singleton_scores/AttributeSingletonScore.h" #include "IMP/UnaryFunction.h" #include "IMP/Particle.h" - +#include <boost/tuple/tuple.hpp> namespace IMP {
@@ -20,8 +20,8 @@ DerivativeAccumulator *da) const { if (da) { - Float d; - float r= f_->evaluate_with_derivative(b->get_value(k_), d); + Float d, r; + boost::tie(d,r) = f_->evaluate_with_derivative(b->get_value(k_)); b->add_to_derivative(k_, d, *da); return r; } else { Index: kernel/src/singleton_scores/TunnelSingletonScore.cpp =================================================================== --- kernel/src/singleton_scores/TunnelSingletonScore.cpp (revision 669) +++ kernel/src/singleton_scores/TunnelSingletonScore.cpp (working copy) @@ -8,7 +8,7 @@
#include "IMP/singleton_scores/TunnelSingletonScore.h" #include "IMP/decorators/XYZDecorator.h" - +#include <boost/tuple/tuple.hpp> namespace IMP {
@@ -58,7 +58,7 @@ // look below if changed Float dist= -std::min(std::min(rd, hdu), hdd) - radius; if (accum) { - score= f_->evaluate_with_derivative(dist, deriv_scalar); + boost::tie(score, deriv_scalar)= f_->evaluate_with_derivative(dist); } else { score= f_->evaluate(dist); } Index: kernel/src/unary_functions/Cosine.cpp =================================================================== --- kernel/src/unary_functions/Cosine.cpp (revision 669) +++ kernel/src/unary_functions/Cosine.cpp (working copy) @@ -18,11 +18,11 @@ - force_constant_ * std::cos(periodicity_ * feature + phase_); }
-Float Cosine::evaluate_with_derivative(Float feature, Float& deriv) const +FloatPair Cosine::evaluate_with_derivative(Float feature) const { - deriv = force_constant_ * periodicity_ - * std::sin(periodicity_ * feature + phase_); - return evaluate(feature); + Float deriv = force_constant_ * periodicity_ + * std::sin(periodicity_ * feature + phase_); + return std::make_pair(evaluate(feature), deriv); }
} // namespace IMP Index: kernel/src/unary_functions/OpenCubicSpline.cpp =================================================================== --- kernel/src/unary_functions/OpenCubicSpline.cpp (revision 669) +++ kernel/src/unary_functions/OpenCubicSpline.cpp (working copy) @@ -66,8 +66,7 @@ * (spacing_ * spacing_) / 6.; }
-Float OpenCubicSpline::evaluate_with_derivative(Float feature, - Float& deriv) const +FloatPair OpenCubicSpline::evaluate_with_derivative(Float feature) const { size_t lowbin = static_cast<size_t>((feature - minrange_) / spacing_); // handle the case where feature ~= maxrange @@ -79,11 +78,11 @@ Float a = 1. - b; float sixthspacing = spacing_ / 6.;
- deriv = (values_[highbin] - values_[lowbin]) / spacing_ - - (3. * a * a - 1.) * sixthspacing * second_derivs_[lowbin] - + (3. * b * b - 1.) * sixthspacing * second_derivs_[highbin]; + Float deriv = (values_[highbin] - values_[lowbin]) / spacing_ + - (3. * a * a - 1.) * sixthspacing * second_derivs_[lowbin] + + (3. * b * b - 1.) * sixthspacing * second_derivs_[highbin];
- return evaluate(feature); + return std::make_pair(evaluate(feature), deriv); }
} // namespace IMP Index: kernel/src/unary_functions/ClosedCubicSpline.cpp =================================================================== --- kernel/src/unary_functions/ClosedCubicSpline.cpp (revision 669) +++ kernel/src/unary_functions/ClosedCubicSpline.cpp (working copy) @@ -82,8 +82,8 @@ * (spacing_ * spacing_) / 6.; }
-Float ClosedCubicSpline::evaluate_with_derivative(Float feature, - Float& deriv) const +FloatPair +ClosedCubicSpline::evaluate_with_derivative(Float feature) const { size_t lowbin = static_cast<size_t>((feature - minrange_) / spacing_); size_t highbin = lowbin + 1; @@ -99,11 +99,11 @@ Float a = 1. - b; float sixthspacing = spacing_ / 6.;
- deriv = (values_[highbin] - values_[lowbin]) / spacing_ + Float deriv = (values_[highbin] - values_[lowbin]) / spacing_ - (3. * a * a - 1.) * sixthspacing * second_derivs_[lowbin] + (3. * b * b - 1.) * sixthspacing * second_derivs_[highbin];
- return evaluate(feature); + return std::make_pair(evaluate(feature), deriv); }
} // namespace IMP Index: kernel/src/restraints/DihedralRestraint.cpp =================================================================== --- kernel/src/restraints/DihedralRestraint.cpp (revision 669) +++ kernel/src/restraints/DihedralRestraint.cpp (working copy) @@ -15,6 +15,8 @@ #include "IMP/restraints/DihedralRestraint.h" #include "IMP/decorators/XYZDecorator.h"
+#include <boost/tuple/tuple.hpp> + namespace IMP {
@@ -80,7 +82,7 @@
if (accum) { Float deriv; - score = score_func_->evaluate_with_derivative(angle, deriv); + boost::tie(score, deriv) = score_func_->evaluate_with_derivative(angle);
// method for derivative calculation from van Schaik et al. // J. Mol. Biol. 234, 751-762 (1993) Index: kernel/src/triplet_scores/AngleTripletScore.cpp =================================================================== --- kernel/src/triplet_scores/AngleTripletScore.cpp (revision 669) +++ kernel/src/triplet_scores/AngleTripletScore.cpp (working copy) @@ -8,7 +8,7 @@ #include "IMP/triplet_scores/AngleTripletScore.h" #include "IMP/decorators/XYZDecorator.h" #include "IMP/UnaryFunction.h" - +#include <boost/tuple/tuple.hpp> namespace IMP {
@@ -46,7 +46,7 @@
if (da) { Float deriv; - score = f_->evaluate_with_derivative(angle, deriv); + boost::tie(score, deriv) = f_->evaluate_with_derivative(angle);
Vector3D unit_rij = rij.get_unit_vector(); Vector3D unit_rkj = rkj.get_unit_vector(); Index: kernel/pyext/IMP.i =================================================================== --- kernel/pyext/IMP.i (revision 669) +++ kernel/pyext/IMP.i (working copy) @@ -14,8 +14,17 @@
/* Return derivatives from unary functions */ %include "typemaps.i" -%apply double &OUTPUT { IMP::Float& deriv };
+namespace IMP { + %typemap(out) std::pair<Float,Float> { + PyObject *tup= PyTuple_New(2); + PyTuple_SetItem(tup, 0, PyFloat_FromDouble($1.first)); + PyTuple_SetItem(tup, 1, PyFloat_FromDouble($1.second)); + $result= tup; + } +} + + %pythoncode %{ def check_particle(p, a): if (not p.get_is_active()): @@ -27,94 +36,30 @@ %}
namespace IMP { - %pythonprepend Model::add_restraint %{ - args[1].thisown=0 - %} - %pythonprepend Model::add_score_state %{ - args[1].thisown=0 - %} - %pythonprepend Optimizer::add_optimizer_state %{ - args[1].thisown=0 - %} - %pythonprepend RestraintSet::add_restraint %{ - args[1].thisown=0 - %} - %pythonprepend NonbondedListScoreState::add_bonded_list %{ - args[1].thisown=0 - %} - %pythonprepend DistanceRestraint::DistanceRestraint %{ - args[0].thisown=0 - %} - %pythonprepend AngleRestraint::AngleRestraint %{ - args[0].thisown=0 - %} - %pythonprepend DihedralRestraint::DihedralRestraint %{ - args[0].thisown=0 - %} - %pythonprepend TorusRestraint::TorusRestraint %{ - args[3].thisown=0 - %} - %pythonprepend NonbondedRestraint::NonbondedRestraint %{ - args[0].thisown=0 - %} - %pythonprepend BondDecoratorRestraint::BondDecoratorRestraint %{ - args[0].thisown=0 - %} - %pythonprepend SingletonListRestraint::SingletonListRestraint %{ - args[0].thisown=0 - %} - %pythonprepend PairListRestraint::PairListRestraint %{ - args[0].thisown=0 - %} - %pythonprepend TripletChainRestraint::TripletChainRestraint %{ - args[0].thisown=0 - %} - %pythonprepend PairChainRestraint::PairChainRestraint %{ - args[0].thisown=0 - %} - %pythonprepend ConnectivityRestraint::ConnectivityRestraint %{ - args[0].thisown=0 - %} - %pythonprepend DistancePairScore::DistancePairScore %{ - args[0].thisown=0 - %} - %pythonprepend TransformedDistancePairScore::TransformedDistancePairScore %{ - args[0].thisown=0 - %} - %pythonprepend BondCoverPairScore::BondCoverPairScore %{ - args[0].thisown=0 - %} - %pythonprepend SphereDistancePairScore::SphereDistancePairScore %{ - args[0].thisown=0 - %} - %pythonprepend RefineOncePairScore::RefineOncePairScore %{ - args[0].thisown=0 - args[1].thisown=0 - %} - %pythonprepend DistanceToSingletonScore::DistanceToSingletonScore %{ - args[0].thisown=0 - %} - %pythonprepend AttributeSingletonScore::AttributeSingletonScore %{ - args[0].thisown=0 - %} - %pythonprepend TunnelSingletonScore::TunnelSingletonScore %{ - args[0].thisown=0 - %} - %pythonprepend AngleTripletScore::AngleTripletScore %{ - args[0].thisown=0 - %} - %pythonprepend MonteCarlo::add_mover %{ - args[1].thisown=0 - %} - %pythonprepend MonteCarlo::set_local_optimizer %{ - args[1].thisown=0 - %} - %pythonprepend VRMLLogOptimizerState::add_particle_refiner %{ - args[1].thisown=0 - %} - %pythonprepend TypedPairScore::set_pair_score %{ - args[1].thisown=0 - %} + // need to special case particle so can't add this to macro + IMP_OWN_FIRST_CONSTRUCTOR(DistanceRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(AngleRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(DihedralRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(TorusRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(NonbondedRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(BondDecoratorRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(SingletonListRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(PairListRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(TripletChainRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(PairChainRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(ConnectivityRestraint) + IMP_OWN_FIRST_CONSTRUCTOR(DistancePairScore) + IMP_OWN_FIRST_CONSTRUCTOR(TransformedDistancePairScore) + IMP_OWN_FIRST_CONSTRUCTOR(BondCoverPairScore) + IMP_OWN_FIRST_CONSTRUCTOR(SphereDistancePairScore) + IMP_OWN_FIRST_SECOND_CONSTRUCTOR(RefineOncePairScore) + IMP_OWN_FIRST_CONSTRUCTOR(DistanceToSingletonScore) + IMP_OWN_FIRST_CONSTRUCTOR(AttributeSingletonScore) + IMP_OWN_FIRST_CONSTRUCTOR(TunnelSingletonScore) + IMP_OWN_FIRST_CONSTRUCTOR(AngleTripletScore) + IMP_SET_OBJECT(MonteCarlo, set_local_optimizer) + IMP_SET_OBJECT(TypedPairScore, set_pair_score) + %pythonprepend Particle::get_value %{ check_particle(args[0], args[1]) %} @@ -144,10 +89,19 @@
%}
- IMP_CONTAINER_SWIG(Model, Particle, particle); + // special case since particles are ref counted + %extend Model { + Particles get_particles() const { + IMP::Particles ret(self->particles_begin(), self->particles_end()); + return ret; + } + } IMP_CONTAINER_SWIG(Model, ScoreState, score_state); IMP_CONTAINER_SWIG(Model, Restraint, restraint); IMP_CONTAINER_SWIG(RestraintSet, Restraint, restraint); + IMP_CONTAINER_SWIG(MonteCarlo, Mover, mover); + IMP_CONTAINER_SWIG(Optimizer, OptimizerState, optimizer_state); + IMP_CONTAINER_SWIG(NonbondedListScoreState, BondedListScoreState, bonded_list); }
%feature("ref") Particle "$this->ref();" @@ -168,6 +122,7 @@ %feature("director") IMP::TripletScore; %feature("director") IMP::Optimizer; %feature("director") IMP::ParticleRefiner; +%feature("director") IMP::Mover;
%include "IMP/Key.h" %include "IMP/Object.h"