Index: kernel/test/states/test_nonbonded_list.py
===================================================================
--- kernel/test/states/test_nonbonded_list.py	(revision 0)
+++ kernel/test/states/test_nonbonded_list.py	(revision 0)
@@ -0,0 +1,33 @@
+import unittest
+import IMP, IMP.test
+import os.path
+
+class OnePair(IMP.PairScore):
+    def evaluate(self, da):
+        return 1
+
+
+class TestNBL(IMP.test.TestCase):
+    def setUp(self):
+        IMP.set_log_level(IMP.TERSE)
+
+    def test_it(self):
+        """Test the nonbonded list and restraint which uses it"""
+        m= IMP.Model()
+        for i in range(0,10):
+            p= IMP.Particle()
+            m.add_particle(p)
+            d=IMP.XYZDecorator.create(p)
+            d.set_x(0)
+            d.set_y(1)
+            d.set_z(1)
+        s= IMP.NonbondedListScoreState(m.get_particles(), 100)
+        m.add_score_state(s)
+        r= IMP.NonbondedRestraint(s, OnePair())
+        m.add_restraint(r)
+        score= m.evaluate()
+        self.assertEqual(score, 45, "Wrong score")
+
+
+if __name__ == '__main__':
+    unittest.main()
Index: kernel/include/IMP/SConscript
===================================================================
--- kernel/include/IMP/SConscript	(revision 326)
+++ kernel/include/IMP/SConscript	(working copy)
@@ -18,3 +18,5 @@
 SConscript('optimizers/SConscript')
 SConscript('decorators/SConscript')
 SConscript('unary_functions/SConscript')
+SConscript('pair_scores/SConscript')
+SConscript('score_states/SConscript')
Index: kernel/include/IMP/utility.h
===================================================================
--- kernel/include/IMP/utility.h	(revision 326)
+++ kernel/include/IMP/utility.h	(working copy)
@@ -40,6 +40,41 @@
     return (field<= o.field);      \
   }
 
+//! Implement comparison in a class using field as the variable to compare
+/** The macro requires that This be defined as the type of the current class.
+ */
+#define IMP_COMPARISONS_2(f0, f1)                                       \
+  /** */ bool operator==(const This &o) const {                         \
+    return (f0== o.f0 && f1==o.f1);                                     \
+  }                                                                     \
+  /** */ bool operator!=(const This &o) const {                         \
+    return (f0!= o.f0 || f1 != o.f1);                                   \
+  }                                                                     \
+  /** */ bool operator<(const This &o) const {                          \
+    IMP_assert(!is_default() && !o.is_default(),                        \
+               "Ordering with uninitialized index is undefined");       \
+    if (f0< o.f0) return true;                                          \
+    else if (f0 > o.f0) return false;                                   \
+    else return f1 < o.f1;                                              \
+  }                                                                     \
+  /** */ bool operator>(const This &o) const {                          \
+    IMP_assert(!is_default() && !o.is_default(),                        \
+               "Ordering with uninitialized index is undefined");       \
+    if (f0 > o.f0) return true;                                         \
+    else if (f0 < o.f0) return false;                                   \
+    else return f1 > o.f1;                                              \
+  }                                                                     \
+  /** */ bool operator>=(const This &o) const {                         \
+    IMP_assert(!is_default() && !o.is_default(),                        \
+               "Ordering with uninitialized index is undefined");       \
+    return operator>(o) || operator==(o);                               \
+  }                                                                     \
+  /** */ bool operator<=(const This &o) const {                         \
+    IMP_assert(!is_default() && !o.is_default(),                        \
+               "Ordering with uninitialized index is undefined");       \
+    return operator<(o) || operator==(o);                               \
+  }
+
 //! Implement operator<< on class name, assuming it has one template argument
 /** class name should also define the method std::ostream &show(std::ostream&)
  */
@@ -92,7 +127,32 @@
   virtual std::string last_modified_by() const {return std::string(lmb_string);}
 
 
+//! Define the basics needed for an OptimizerState
+/**
+   This macro declares the required functions 
+   - void update()
+   - void show(std::ostream &out) const
+   and defines the functions
+   - version
+   - last_modified_by
 
+   \param[in] version_string The version.
+   \param[in] lmb_string The person who last modified it.
+*/
+#define IMP_OPTIMIZER_STATE(version_string, lmb_string)                 \
+  /** update the state*/                                                \
+  virtual void update();                                                \
+  /** write information about the state to the stream*/                 \
+  virtual void show(std::ostream &out=std::cout) const;                 \
+  /** \return the current version*/                                     \
+  virtual std::string version() const {return std::string(version_string);} \
+  /** \return the last person to modify this restraint */               \
+  virtual std::string last_modified_by() const {return std::string(lmb_string);}
+
+//! See IMP_OPTIMIZER_STATE
+#define IMP_SCORE_STATE(version_string, lmb_string)\
+  IMP_OPTIMIZER_STATE(version_string, lmb_string)
+
 //! Use the swap_with member function to swap two objects
 #define IMP_SWAP(name) \
   inline void swap(name &a, name &b) {          \
Index: kernel/include/IMP/score_states/NonbondedListScoreState.h
===================================================================
--- kernel/include/IMP/score_states/NonbondedListScoreState.h	(revision 0)
+++ kernel/include/IMP/score_states/NonbondedListScoreState.h	(revision 0)
@@ -0,0 +1,59 @@
+/**
+ *  \file NonbondedListScoreState.h    
+ *  \brief Allow iteration through pairs of a set of atoms.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#ifndef __IMP_NONBONDEDLISTSCORESTATE_H
+#define __IMP_NONBONDEDLISTSCORESTATE_H
+
+#include "../ScoreState.h"
+#include "BondedListScoreState.h"
+#include <vector>
+#include <limits>
+
+namespace IMP
+{
+  class BondedListScoreState;
+  //! This class maintains a list of non-bonded pairs.
+  /**
+     The distance cutoff is an optimization hint rather than a 
+     strict cutoff. That is, the NonbondedListScoreState may
+     choose to ignore pairs above that cutoff, but may not.
+   */
+  class IMPDLLEXPORT NonbondedListScoreState: public ScoreState {
+    Particles ps_;
+    typedef std::vector<std::pair<Particle*, Particle*> > NBL;
+    NBL nbl_;
+    float dist_cutoff_;
+
+    void rescan();
+
+  public:
+    NonbondedListScoreState(const Particles &ps, 
+                            float dist_cutoff
+                            =std::numeric_limits<Float>::max());
+    virtual ~NonbondedListScoreState(){}
+    IMP_CONTAINER(BondedListScoreState, bonded_list_score_state,
+                  BondedListIndex);
+  public:
+    IMP_SCORE_STATE("0.5", "Daniel Russel");
+
+    void set_particles(const Particles &ps);
+
+    //! This iterates through the pairs of non-bonded particles
+    /**
+       \precondition update() must be called first for this to be valid.
+     */
+    typedef NBL::const_iterator NonbondedIterator;
+    NonbondedIterator nonbonded_begin() const {
+      return nbl_.begin();
+    }
+    NonbondedIterator nonbonded_end() const {
+      return nbl_.end();
+    }
+  };
+
+}
+#endif
Index: kernel/include/IMP/score_states/SConscript
===================================================================
--- kernel/include/IMP/score_states/SConscript	(revision 0)
+++ kernel/include/IMP/score_states/SConscript	(revision 0)
@@ -0,0 +1,9 @@
+import os.path
+Import('env')
+
+files = ['BondedListScoreState.h', 'NonbondedListScoreState.h']
+
+# Install the include files:
+includedir = os.path.join(env['includedir'], 'IMP', 'score_states')
+inst = env.Install(includedir, files)
+env.Alias('install', inst)
Index: kernel/include/IMP/score_states/BondedListScoreState.h
===================================================================
--- kernel/include/IMP/score_states/BondedListScoreState.h	(revision 0)
+++ kernel/include/IMP/score_states/BondedListScoreState.h	(revision 0)
@@ -0,0 +1,55 @@
+/**
+ *  \file BondedListScoreState.h    
+ *  \brief Allow iteration through pairs of a set of atoms.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#ifndef __IMP_BONDEDLISTSCORESTATE_H
+#define __IMP_BONDEDLISTSCORESTATE_H
+
+#include "../ScoreState.h"
+#include "../Index.h"
+#include "../Particle.h"
+#include <set>
+
+namespace IMP
+{
+  class BondedListScoreState;
+  typedef Index<BondedListScoreState> BondedListIndex;
+
+  //! This abstract class maintains a list of bonded pairs.
+  class IMPDLLEXPORT BondedListScoreState: public ScoreState {
+    struct BP: public std::pair<Particle*, Particle *> {
+      typedef BP This;
+      typedef std::pair<Particle*, Particle *> P;
+      BP(): P(NULL, NULL){}
+      bool is_default() const {return first==NULL && second==NULL;}
+      BP(Particle* a, Particle *b): P(std::min(a,b),std::max(a,b)){}
+      IMP_COMPARISONS_2(first, second);
+    };
+    //std::set<BP> bonds_;
+
+  public:
+    BondedListScoreState(){}
+    virtual ~BondedListScoreState(){}
+    //IMP_SCORE_STATE("0.5", "Daniel Russel");
+
+    virtual bool are_bonded(Particle *a, Particle *b) const =0;
+#if 0
+    //! This iterates through the pairs of non-bonded particles
+    /**
+       \precondition update() must be called first for this to be valid.
+     */
+    typedef std::set<BP>::const_iterator BondedIterator;
+    BondedIterator bonded_begin() const {
+      return bonds_.begin();
+    }
+    BondedIterator bonded_end() const {
+      return bonds_.end();
+    }
+#endif
+  };
+
+}
+#endif
Index: kernel/include/IMP/restraints/SConscript
===================================================================
--- kernel/include/IMP/restraints/SConscript	(revision 326)
+++ kernel/include/IMP/restraints/SConscript	(working copy)
@@ -4,7 +4,7 @@
 files = ['ConnectivityRestraint.h', 'ProximityRestraint.h',
          'SphericalRestraint.h', 'DistanceRestraint.h', 'AngleRestraint.h',
          'DihedralRestraint.h', 'RestraintSet.h', 'ExclusionVolumeRestraint.h',
-         'TorusRestraint.h', 'PairConnectivityRestraint.h']
+         'TorusRestraint.h', 'PairConnectivityRestraint.h', 'NonbondedRestraint.h']
 
 # Install the include files:
 includedir = os.path.join(env['includedir'], 'IMP', 'restraints')
Index: kernel/include/IMP/restraints/NonbondedRestraint.h
===================================================================
--- kernel/include/IMP/restraints/NonbondedRestraint.h	(revision 0)
+++ kernel/include/IMP/restraints/NonbondedRestraint.h	(revision 0)
@@ -0,0 +1,50 @@
+/**
+ *  \file NonbondedRestraint.h   
+ *  \brief Apply a PairScore to all nonbonded pairs.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#ifndef __IMP_NEARBYPAIRS_RESTRAINT_H
+#define __IMP_NEARBYPAIRS_RESTRAINT_H
+
+#include <vector>
+#include <iostream>
+
+#include "../IMP_config.h"
+#include "../ModelData.h"
+#include "../Restraint.h"
+
+
+namespace IMP
+{
+
+class NonbondedListScoreState;
+class PairScore;
+
+//! Restraint all pairs of non-bonded particles
+/**
+ */
+class IMPDLLEXPORT NonbondedRestraint : public Restraint
+{
+public:
+  //! Create the nonbonded restraint.
+  /** \param[in] nbl The non-bonded list to use to get the list
+      of particles.
+      \param[in] ps The pair score function to apply to the pairs. This 
+      object is deleted upon destruction.
+   */
+  NonbondedRestraint(NonbondedListScoreState *nbl, PairScore *ps );
+  virtual ~NonbondedRestraint(){}
+
+  IMP_RESTRAINT("0.5", "Daniel Russel");
+
+ protected:
+  NonbondedListScoreState *nbl_;
+  std::auto_ptr<PairScore> sf_;
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_NONBONDED_RESTRAINT_H */
Index: kernel/include/IMP/restraints/DistanceRestraint.h
===================================================================
--- kernel/include/IMP/restraints/DistanceRestraint.h	(revision 326)
+++ kernel/include/IMP/restraints/DistanceRestraint.h	(working copy)
@@ -12,8 +12,7 @@
 #include <iostream>
 
 #include "../IMP_config.h"
-#include "../ModelData.h"
-#include "../UnaryFunction.h"
+#include "../pair_scores/DistancePairScore.h"
 #include "../Restraint.h"
 
 
@@ -35,13 +34,13 @@
    */
   DistanceRestraint(Particle* p1, Particle* p2,
                     UnaryFunction* score_func);
-  virtual ~DistanceRestraint();
+  virtual ~DistanceRestraint(){}
 
   IMP_RESTRAINT("0.5", "Daniel Russel")
 
 protected:
   //! scoring function for this restraint
-  UnaryFunction* score_func_;
+  DistancePairScore dp_;
 };
 
 } // namespace IMP
Index: kernel/include/IMP/decorators/graph_base.h
===================================================================
--- kernel/include/IMP/decorators/graph_base.h	(revision 326)
+++ kernel/include/IMP/decorators/graph_base.h	(working copy)
@@ -102,4 +102,115 @@
 
 } // namespace IMP
 
+//! Define a class of graphs
+/**
+   This defines several methods. It depends on there being a class
+   UCNameDecorator which defines the edges data. It also requires that
+   the method 
+   - UCNameDecorator lcname(UCNamedDecorator, UCNamedDecorator)
+   be defined.
+*/
+#define IMP_DECLARE_GRAPH(UCName, lcname)                               \
+  class UCName##Decorator;                                              \
+  class UCName##edDecorator;                                            \
+                                                                        \
+  namespace internal                                                    \
+  {                                                                     \
+    extern IMPDLLEXPORT  GraphData lcname##_graph_data_;                \
+    extern IMPDLLEXPORT  bool lcname##_keys_initialized_;               \
+  }                                                                     \
+                                                                        \
+                                                                        \
+  /**\brief A decorator for a particle which has bonds. */              \
+  class IMPDLLEXPORT UCName##edDecorator: public DecoratorBase          \
+  {                                                                     \
+    IMP_DECORATOR(UCName##edDecorator, DecoratorBase, return true, );   \
+  public:                                                               \
+    unsigned int get_number_of_##lcname##s() const {                    \
+      return graph_get_number_of_edges(get_particle(),                  \
+                                       internal::lcname##_graph_data_); \
+    }                                                                   \
+                                                                        \
+                                                                        \
+    /**\brief Get a BondDecorator of the ith child
+       \return decorator of the ith child, or throw and exception if there
+       is no such bond
+    */                                                  \
+UCName##Decorator get_##lcname(unsigned int i) const {  \
+  Particle *p= graph_get_edge(get_particle(), i,                \
+                              internal::lcname##_graph_data_);  \
+  return UCName##Decorator::cast(p);                                \
+}                                                                   \
+};                                                                  \
+                                                                    \
+IMP_OUTPUT_OPERATOR(BondedDecorator);                               \
+                                                                    \
+                                                                    \
+UCName##edDecorator                                                     \
+UCName##Decorator::get_##lcname##ed(unsigned int i) const               \
+{                                                                       \
+  Particle *p= graph_get_node(get_particle(), i,                        \
+                              internal::lcname##_graph_data_);          \
+  return UCName##edDecorator::cast(p);                                  \
+}                                                                       \
+                                                                        \
+                                                                        \
+/** \brief Destroy the bond connecting two particles.
+    \param[in] b The bond.
+*/                                              \
+IMPDLLEXPORT                                    \
+void un#lcname(UCName##Decorator b);            \
+                                                \
+                                                \
+/**
+   \brief Get the bond between two particles.
+   BondDecorator() is returned if the particles are not bonded.
+*/                                                              \
+IMPDLLEXPORT UCName##Decorator                                  \
+get_##lcname(UCName##edDecorator a, UCName##edDecorator b);
+
+
+#define IMP_DEFINE_GRAPH(UCName, lcname)                                \
+  namespace internal                                                    \
+  {                                                                     \
+    GraphData lcname##_graph_data_;                                     \
+    bool lcname##_keys_initialized_=false;                              \
+  }                                                                     \
+                                                                        \
+                                                                        \
+  void UCName##Decorator                                                \
+  ::show(std::ostream &out, std::string) const                          \
+  {                                                                     \
+    out << #UCName " between "                                         \
+        << get_##lcname##ed(0).get_particle()->get_index() << " and "   \
+        << get_##lcname##ed(1).get_particle()->get_index()              \
+        << " of type " << get_type() << " and order " << get_order()    \
+        << std::endl;                                                   \
+  }                                                                     \
+                                                                        \
+                                                                        \
+  IMP_DECORATOR_INITIALIZE(UCName##Decorator, DecoratorBase,            \
+                           lcname##_initialize_static_data());          \
+                                                                        \
+                                                                        \
+                                                                        \
+                                                                        \
+  void un##lcname(UCName##Decorator b) {                                \
+    graph_disconnect(b.get_particle(), internal::lcname##_graph_data_); \
+  }                                                                     \
+                                                                        \
+  UCName##Decorator                                                     \
+  get_##lcname(UCName##edDecorator a, UCName##edDecorator b) {          \
+    for (unsigned int i=0; i < a.get_number_of_##lcname##s(); ++i) {    \
+      UCName##Decorator bd= a.get_##lcname(i);                          \
+      if (bd.get_##lcname(0) == b || bd.get_##lcname(1) == b) {         \
+        return bd;                                                      \
+      }                                                                 \
+    }                                                                   \
+    return UCName##Decorator();                                         \
+  }                                                                     \
+
+
+// define method setup_##lcname to do the combinatorial work for a bond
+// check why I need bond?
 #endif  /* __IMP_GRAPH_DECORATORS_H */
Index: kernel/include/IMP/pair_scores/SphereDistancePairScore.h
===================================================================
--- kernel/include/IMP/pair_scores/SphereDistancePairScore.h	(revision 0)
+++ kernel/include/IMP/pair_scores/SphereDistancePairScore.h	(revision 0)
@@ -0,0 +1,35 @@
+/**
+ *  \file SphereDistancePairScore.h    
+ *  \brief A Score on the distance between a pair of spheres.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#ifndef __IMP_SPAIRSCORE_H
+#define __IMP_SPAIRSCORE_H
+
+#include "../PairScore.h"
+
+namespace IMP
+{
+class UnaryFunction;
+
+//! Apply a function to the distance between two particles.
+/** 
+ */
+class IMPDLLEXPORT SphereDistancePairScore : public PairScore
+{
+  std::auto_ptr<UnaryFunction> f_;
+  FloatKey radius_;
+public:
+  SphereDistancePairScore(UnaryFunction *f, 
+                          FloatKey radius=FloatKey("radius"));
+  virtual ~SphereDistancePairScore(){}
+  virtual Float evaluate(Particle *a, Particle *b,
+                         DerivativeAccumulator *da);
+  virtual void show(std::ostream &out=std::cout) const;
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_SPHEREDISTANCEPAIRSCORE_H */
Index: kernel/include/IMP/pair_scores/SConscript
===================================================================
--- kernel/include/IMP/pair_scores/SConscript	(revision 0)
+++ kernel/include/IMP/pair_scores/SConscript	(revision 0)
@@ -0,0 +1,9 @@
+import os.path
+Import('env')
+
+files = ['DistancePairScore.h', 'SphereDistancePairScore.h']
+
+# Install the include files:
+includedir = os.path.join(env['includedir'], 'IMP', 'pair_scores')
+inst = env.Install(includedir, files)
+env.Alias('install', inst)
Index: kernel/include/IMP/pair_scores/DistancePairScore.h
===================================================================
--- kernel/include/IMP/pair_scores/DistancePairScore.h	(revision 0)
+++ kernel/include/IMP/pair_scores/DistancePairScore.h	(revision 0)
@@ -0,0 +1,33 @@
+/**
+ *  \file DistancePairScore.h    
+ *  \brief A Score on the distance between a pair of particles.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#ifndef __IMP_DPAIRSCORE_H
+#define __IMP_DPAIRSCORE_H
+
+#include "../PairScore.h"
+#include "../UnaryFunction.h"
+
+namespace IMP
+{
+
+//! Apply a function to the distance between two particles.
+/** 
+ */
+class IMPDLLEXPORT DistancePairScore : public PairScore
+{
+  std::auto_ptr<UnaryFunction> f_;
+public:
+  DistancePairScore(UnaryFunction *f);
+  virtual ~DistancePairScore(){}
+  virtual Float evaluate(Particle *a, Particle *b,
+                           DerivativeAccumulator *da);
+  virtual void show(std::ostream &out=std::cout) const;
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_DISTANCEPAIRSCORE_H */
Index: kernel/include/IMP/PairScore.h
===================================================================
--- kernel/include/IMP/PairScore.h	(revision 0)
+++ kernel/include/IMP/PairScore.h	(revision 0)
@@ -0,0 +1,35 @@
+/**
+ *  \file PairScore.h    \brief A Score on a pair of particles.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#ifndef __IMP_PAIRSCORE_H
+#define __IMP_PAIRSCORE_H
+
+#include "IMP_config.h"
+#include "base_types.h"
+#include "Object.h"
+#include "Particle.h"
+#include "DerivativeAccumulator.h"
+
+namespace IMP
+{
+
+//! Abstract score function for a pair of particles.
+/** 
+ */
+class IMPDLLEXPORT PairScore : public Object
+{
+public:
+  PairScore() {}
+  virtual ~PairScore() {}
+  //! Compute the score for the pair and the deriv if needed.
+  virtual Float evaluate(Particle *a, Particle *b,
+                         DerivativeAccumulator *da) = 0;
+  virtual void show(std::ostream &out=std::cout) const = 0;
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_PAIRSCORE_H */
Index: kernel/include/IMP.h
===================================================================
--- kernel/include/IMP.h	(revision 326)
+++ kernel/include/IMP.h	(working copy)
@@ -23,6 +23,7 @@
 #include "IMP/RigidBody.h"
 #include "IMP/ModelData.h"
 #include "IMP/Model.h"
+#include "IMP/PairScore.h"
 #include "IMP/Vector3D.h"
 #include "IMP/decorators/HierarchyDecorator.h"
 #include "IMP/decorators/MolecularHierarchyDecorator.h"
@@ -35,6 +36,8 @@
 #include "IMP/optimizers/ConjugateGradients.h"
 #include "IMP/optimizers/MolecularDynamics.h"
 #include "IMP/optimizers/states/VRMLLogOptimizerState.h"
+#include "IMP/pair_scores/DistancePairScore.h"
+#include "IMP/pair_scores/SphereDistancePairScore.h"
 #include "IMP/restraints/RestraintSet.h"
 #include "IMP/restraints/DistanceRestraint.h"
 #include "IMP/restraints/AngleRestraint.h"
@@ -45,6 +48,9 @@
 #include "IMP/restraints/ConnectivityRestraint.h"
 #include "IMP/restraints/PairConnectivityRestraint.h"
 #include "IMP/restraints/ExclusionVolumeRestraint.h"
+#include "IMP/restraints/NonbondedRestraint.h"
+#include "IMP/score_states/NonbondedListScoreState.h"
+#include "IMP/score_states/BondedListScoreState.h"
 
 /**
    \namespace IMP The IMP namespace.
Index: kernel/src/SConscript
===================================================================
--- kernel/src/SConscript	(revision 326)
+++ kernel/src/SConscript	(working copy)
@@ -9,6 +9,8 @@
 optimizers_files = SConscript('optimizers/SConscript')
 decorators_files = SConscript('decorators/SConscript')
 unary_functions_files = SConscript('unary_functions/SConscript')
+pair_scores_files = SConscript('pair_scores/SConscript')
+score_states_files = SConscript('score_states/SConscript')
 
 # Source files
 files = ['base_types.cpp', 'Model.cpp', 'ModelData.cpp',
@@ -16,7 +18,7 @@
          'OptimizerState.cpp', 'Log.cpp', 'Restraint.cpp', 'Optimizer.cpp',
          'Object.cpp', 'BasicScoreFuncParams.cpp'
         ] + decorators_files + restraints_files + optimizers_files \
-          + unary_functions_files
+          + unary_functions_files + pair_scores_files + score_states_files
 
 # Build the shared library:
 lib = env.SharedLibrary('imp', files)
Index: kernel/src/score_states/NonbondedListScoreState.cpp
===================================================================
--- kernel/src/score_states/NonbondedListScoreState.cpp	(revision 0)
+++ kernel/src/score_states/NonbondedListScoreState.cpp	(revision 0)
@@ -0,0 +1,52 @@
+/**
+ *  \file NonbondedListScoreState.cpp  
+ *  \brief Allow iteration through pairs of a set of atoms.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#include "IMP/score_states/NonbondedListScoreState.h"
+
+namespace IMP {
+  NonbondedListScoreState::NonbondedListScoreState(const Particles &ps,
+                                                   float dist_cutoff):
+    dist_cutoff_(dist_cutoff)
+  {
+    set_particles(ps);
+  }
+
+  void NonbondedListScoreState::rescan() {
+    nbl_.clear();
+    for (unsigned int i=0; i< ps_.size(); ++i) {
+      Particle *pi= ps_[i];
+      for (unsigned int j=0; j < i; ++j) {
+        Particle *pj= ps_[j];
+        bool found=false;
+        for (BondedListScoreStateIterator bli= bonded_list_score_states_begin();
+             bli != bonded_list_score_states_end(); ++bli) {
+          if ((*bli)->are_bonded(pi, pj)) {
+            found=true;
+            break;
+          }
+        }
+        if (!found) {
+          nbl_.push_back(std::make_pair(pi, pj));
+        }
+      }
+    }
+  }
+
+  void NonbondedListScoreState::set_particles(const Particles &ps) {
+    ps_=ps;
+    rescan();
+  }
+  void NonbondedListScoreState::update() {
+    rescan();
+  }
+  void NonbondedListScoreState::show(std::ostream &out) const {
+    out << "NonbondedList" << std::endl;
+  }
+
+  IMP_CONTAINER_IMPL(NonbondedListScoreState, BondedListScoreState,
+                     bonded_list_score_state, BondedListIndex, );
+}
Index: kernel/src/score_states/BondedListScoreState.cpp
===================================================================
--- kernel/src/score_states/BondedListScoreState.cpp	(revision 0)
+++ kernel/src/score_states/BondedListScoreState.cpp	(revision 0)
@@ -0,0 +1,11 @@
+/**
+ *  \file BondedListScoreState.cpp 
+ *  \brief Allow iteration through pairs of a set of atoms.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+#include "IMP/score_states/BondedListScoreState.h"
+
+namespace IMP {
+
+}
Index: kernel/src/score_states/SConscript
===================================================================
--- kernel/src/score_states/SConscript	(revision 0)
+++ kernel/src/score_states/SConscript	(revision 0)
@@ -0,0 +1,6 @@
+Import('env')
+
+files = ['BondedListScoreState.cpp', 'NonbondedListScoreState.cpp']
+
+files = [File(x) for x in files]
+Return('files')
Index: kernel/src/restraints/NonbondedRestraint.cpp
===================================================================
--- kernel/src/restraints/NonbondedRestraint.cpp	(revision 0)
+++ kernel/src/restraints/NonbondedRestraint.cpp	(revision 0)
@@ -0,0 +1,49 @@
+/**
+ *  \file NonbondedRestraint.cpp 
+ *  \brief A nonbonded restraint.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#include <cmath>
+
+#include "IMP/PairScore.h"
+#include "IMP/log.h"
+#include "IMP/restraints/NonbondedRestraint.h"
+#include "IMP/score_states/NonbondedListScoreState.h"
+
+namespace IMP
+{
+
+NonbondedRestraint::NonbondedRestraint(NonbondedListScoreState *nbl, 
+                                       PairScore *ps )
+  : nbl_(nbl), sf_(ps)
+{
+}
+
+
+Float NonbondedRestraint::evaluate(DerivativeAccumulator *accum)
+{
+
+  IMP_CHECK_OBJECT(sf_);
+  IMP_CHECK_OBJECT(nbl_);
+  Float score=0;
+
+  for (NonbondedListScoreState::NonbondedIterator it=  nbl_->nonbonded_begin();
+       it != nbl_->nonbonded_end(); ++it) {
+    sf_->evaluate(it->first, it->second, accum);
+  }
+
+  return score;
+}
+
+
+void NonbondedRestraint::show(std::ostream& out) const
+{
+  out << "Nonbonded restraint with score function ";
+  sf_->show(out);
+  out << std::endl;
+}
+
+}  // namespace IMP
Index: kernel/src/restraints/DistanceRestraint.cpp
===================================================================
--- kernel/src/restraints/DistanceRestraint.cpp	(revision 326)
+++ kernel/src/restraints/DistanceRestraint.cpp	(working copy)
@@ -12,6 +12,7 @@
 #include "IMP/log.h"
 #include "IMP/restraints/DistanceRestraint.h"
 #include "IMP/decorators/XYZDecorator.h"
+#include "IMP/pair_scores/DistancePairScore.h"
 
 namespace IMP
 {
@@ -20,22 +21,13 @@
 static const Float MIN_DISTANCE = 0.0000001;
 
 DistanceRestraint::DistanceRestraint(Particle* p1, Particle* p2,
-                                     UnaryFunction* score_func)
+                                     UnaryFunction* score_func): 
+  dp_(score_func)
 {
   add_particle(p1);
   add_particle(p2);
-
-  score_func_ = score_func;
 }
 
-
-//! Destructor
-DistanceRestraint::~DistanceRestraint()
-{
-  delete score_func_;
-}
-
-
 //! Calculate the score for this distance restraint.
 /** \param[in] accum If not NULL, use this object to accumulate partial first
                      derivatives.
@@ -43,48 +35,7 @@
  */
 Float DistanceRestraint::evaluate(DerivativeAccumulator *accum)
 {
-
-  IMP_CHECK_OBJECT(score_func_);
-
-  Float d2=0, delta[3];
-  Float score;
-
-  XYZDecorator d0= XYZDecorator::cast(get_particle(0));
-  XYZDecorator d1= XYZDecorator::cast(get_particle(1));
-  for (int i=0; i< 3; ++i ){
-    delta[i]= d0.get_coordinate(i)- d1.get_coordinate(i);
-    d2+= square(delta[i]);
-  }
-
-  Float distance = std::sqrt(d2);
-
-  // if needed, calculate the partial derivatives of the scores with respect
-  // to the particle attributes
-  // avoid division by zero if the distance is too small
-  if (accum && distance >= MIN_DISTANCE) {
-    Float deriv;
-
-    // calculate the score and feature derivative based on the distance feature
-    score = (*score_func_)(distance, deriv);
-
-    for (int i=0; i< 3; ++i ){
-      Float d= delta[i]/distance*deriv;
-      d0.add_to_coordinate_derivative(i, d, *accum);
-      d1.add_to_coordinate_derivative(i, -d, *accum);
-    }
-
-  }
-
-  else {
-    // calculate the score based on the distance feature
-    score = (*score_func_)(distance);
-  }
-
-  IMP_LOG(VERBOSE, "For " << get_particle(0)->get_index() 
-          << " and " << get_particle(1)->get_index() 
-          << " distance: " << distance 
-          << " score: " << score << std::endl);
-  return score;
+  return dp_.evaluate(get_particle(0), get_particle(1), accum);
 }
 
 
@@ -104,7 +55,7 @@
   out << "  particles: " << get_particle(0)->get_index();
   out << " and " << get_particle(1)->get_index();
   out << "  ";
-  score_func_->show(out);
+  dp_.show(out);
   out << std::endl;
 }
 
Index: kernel/src/restraints/SConscript
===================================================================
--- kernel/src/restraints/SConscript	(revision 326)
+++ kernel/src/restraints/SConscript	(working copy)
@@ -4,7 +4,8 @@
          'ConnectivityRestraint.cpp', 'ProximityRestraint.cpp',
          'SphericalRestraint.cpp', 'RestraintSet.cpp',
          'DistanceRestraint.cpp', 'AngleRestraint.cpp', 'DihedralRestraint.cpp',
-         'TorusRestraint.cpp', 'ExclusionVolumeRestraint.cpp']
+         'TorusRestraint.cpp', 'ExclusionVolumeRestraint.cpp',
+         'NonbondedRestraint.cpp']
 
 files = [File(x) for x in files]
 Return('files')
Index: kernel/src/decorators/bond_decorators.cpp
===================================================================
--- kernel/src/decorators/bond_decorators.cpp	(revision 326)
+++ kernel/src/decorators/bond_decorators.cpp	(working copy)
@@ -16,7 +16,6 @@
 
 GraphData bond_graph_data_;
 bool bond_keys_initialized_=false;
-FloatKey bond_length_key_;
 IntKey bond_type_key_;
 IntKey bond_order_key_;
 
Index: kernel/src/pair_scores/DistancePairScore.cpp
===================================================================
--- kernel/src/pair_scores/DistancePairScore.cpp	(revision 0)
+++ kernel/src/pair_scores/DistancePairScore.cpp	(revision 0)
@@ -0,0 +1,65 @@
+/**
+ *  \file DistancePairScore.cpp   
+ *  \brief A Score on the distance between a pair of particles.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#include "IMP/pair_scores/DistancePairScore.h"
+#include "IMP/decorators/XYZDecorator.h"
+#include "IMP/UnaryFunction.h"
+
+namespace IMP {
+
+  static const Float MIN_DISTANCE=.00001;
+
+  DistancePairScore::DistancePairScore(UnaryFunction *f): f_(f){}
+
+  Float DistancePairScore::evaluate(Particle *a, Particle *b,
+                                    DerivativeAccumulator *da) {
+    IMP_CHECK_OBJECT(f_);
+
+    Float d2=0, delta[3];
+    Float score;
+
+    XYZDecorator d0= XYZDecorator::cast(a);
+    XYZDecorator d1= XYZDecorator::cast(b);
+    for (int i=0; i< 3; ++i ){
+      delta[i]= d0.get_coordinate(i)- d1.get_coordinate(i);
+      d2+= square(delta[i]);
+    }
+
+    Float distance = std::sqrt(d2);
+
+    // if needed, calculate the partial derivatives of the scores with respect
+    // to the particle attributes
+    // avoid division by zero if the distance is too small
+    if (da && distance >= MIN_DISTANCE) {
+      Float deriv;
+
+      score = (*f_)(distance, deriv);
+
+      for (int i=0; i< 3; ++i ){
+        Float d= delta[i]/distance*deriv;
+        d0.add_to_coordinate_derivative(i, d, *da);
+        d1.add_to_coordinate_derivative(i, -d, *da);
+      }
+    }
+    else {
+      // calculate the score based on the distance feature
+      score = (*f_)(distance);
+    }
+
+    IMP_LOG(VERBOSE, "For " << a->get_index() 
+            << " and " << b->get_index() 
+            << " distance: " << distance 
+            << " score: " << score << std::endl);
+    return score;
+  }
+
+  void DistancePairScore::show(std::ostream &out) const {
+    out << "DistancePairScore using ";
+    f_->show(out);
+  }
+
+}
Index: kernel/src/pair_scores/SConscript
===================================================================
--- kernel/src/pair_scores/SConscript	(revision 0)
+++ kernel/src/pair_scores/SConscript	(revision 0)
@@ -0,0 +1,6 @@
+Import('env')
+
+files = ['DistancePairScore.cpp', 'SphereDistancePairScore.cpp']
+
+files = [File(x) for x in files]
+Return('files')
Index: kernel/src/pair_scores/SphereDistancePairScore.cpp
===================================================================
--- kernel/src/pair_scores/SphereDistancePairScore.cpp	(revision 0)
+++ kernel/src/pair_scores/SphereDistancePairScore.cpp	(revision 0)
@@ -0,0 +1,71 @@
+/**
+ *  \file SphereDistancePairScore.cpp   
+ *  \brief A Score on the distance between a pair of particles.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#include "IMP/pair_scores/SphereDistancePairScore.h"
+#include "IMP/decorators/XYZDecorator.h"
+#include "IMP/UnaryFunction.h"
+
+namespace IMP {
+
+  static const Float MIN_DISTANCE =.00001;
+
+  SphereDistancePairScore::SphereDistancePairScore(UnaryFunction *f,
+                                                   FloatKey radius): f_(f),
+                                                          radius_(radius){}
+
+  Float SphereDistancePairScore::evaluate(Particle *a, Particle *b,
+                                          DerivativeAccumulator *da) {
+    IMP_CHECK_OBJECT(f_);
+
+    Float d2=0, delta[3];
+    Float score;
+
+    XYZDecorator d0= XYZDecorator::cast(a);
+    XYZDecorator d1= XYZDecorator::cast(b);
+    for (int i=0; i< 3; ++i ){
+      delta[i]= d0.get_coordinate(i)- d1.get_coordinate(i);
+      d2+= square(delta[i]);
+    }
+
+    Float distance = std::sqrt(d2);
+    Float ra= a->get_value(radius_);
+    Float rb= b->get_value(radius_);
+    Float shifted_distance = distance- (ra+rb);
+
+    // if needed, calculate the partial derivatives of the scores with respect
+    // to the particle attributes
+    // avoid division by zero if the distance is too small
+    if (da && distance >= MIN_DISTANCE) {
+      Float deriv;
+
+      score = (*f_)(shifted_distance, deriv);
+
+      for (int i=0; i< 3; ++i ){
+        Float d= delta[i]/distance*deriv;
+        d0.add_to_coordinate_derivative(i, d, *da);
+        d1.add_to_coordinate_derivative(i, -d, *da);
+      }
+    }
+
+    else {
+      // calculate the score based on the distance feature
+      score = (*f_)(shifted_distance);
+    }
+
+    IMP_LOG(VERBOSE, "For " << a->get_index() 
+            << " and " << b->get_index() 
+            << " distance: " << distance 
+            << " score: " << score << std::endl);
+    return score;
+  }
+
+  void SphereDistancePairScore::show(std::ostream &out) const {
+    out << "SphereDistancePairScore using ";
+    f_->show(out);
+  }
+
+}
Index: kernel/pyext/IMP_macros.i
===================================================================
--- kernel/pyext/IMP_macros.i	(revision 326)
+++ kernel/pyext/IMP_macros.i	(working copy)
@@ -35,3 +35,12 @@
 const std::vector<Ucname*> &get_##lcname##s() const {\
       return lcname##_vector_;}\
 
+ #define IMP_OPTIMIZER_STATE(version_string, lmb_string)                 \
+  virtual void update();                                                \
+  virtual void show(std::ostream &out=std::cout) const;                 \
+  virtual std::string version() const {return std::string(version_string);} \
+  virtual std::string last_modified_by() const {return std::string(lmb_string);}
+
+
+#define IMP_SCORE_STATE(version_string, lmb_string)\
+  IMP_OPTIMIZER_STATE(version_string, lmb_string)
Index: kernel/pyext/IMP.i
===================================================================
--- kernel/pyext/IMP.i	(revision 326)
+++ kernel/pyext/IMP.i	(working copy)
@@ -66,6 +66,7 @@
 %include "IMP/OptimizerState.h"
 %include "IMP/log.h"
 %include "IMP/Model.h"
+%include "IMP/PairScore.h"
 %include "IMP/Particle.h"
 %include "IMP/Vector3D.h"
 %include "IMP/DecoratorBase.h"
@@ -82,6 +83,8 @@
 %include "IMP/optimizers/ConjugateGradients.h"
 %include "IMP/optimizers/MolecularDynamics.h"
 %include "IMP/optimizers/states/VRMLLogOptimizerState.h"
+%include "IMP/pair_scores/DistancePairScore.h"
+%include "IMP/pair_scores/SphereDistancePairScore.h"
 %include "IMP/restraints/DistanceRestraint.h"
 %include "IMP/restraints/AngleRestraint.h"
 %include "IMP/restraints/DihedralRestraint.h"
@@ -91,6 +94,8 @@
 %include "IMP/restraints/ConnectivityRestraint.h"
 %include "IMP/restraints/PairConnectivityRestraint.h"
 %include "IMP/restraints/ExclusionVolumeRestraint.h"
+%include "IMP/score_states/BondedListScoreState.h"
+%include "IMP/score_states/NonbondedListScoreState.h"
 %include "IMP/RigidBody.h"
 
 namespace IMP {