Index: kernel/test/restraints/test_pairchain.py
===================================================================
--- kernel/test/restraints/test_pairchain.py	(revision 0)
+++ kernel/test/restraints/test_pairchain.py	(revision 0)
@@ -0,0 +1,46 @@
+import unittest
+import IMP, IMP.test
+
+class IndexDiff(IMP.PairScore):
+    def __init__(self):
+        IMP.PairScore.__init__(self)
+    def evaluate(self, pa, pb, da):
+        d= (pa.get_index().get_index()- pb.get_index().get_index())
+        print d
+        return abs(d)
+    def get_version_info(self):
+        return IMP.VersionInfo("Me", "0.5")
+    def show(self, t):
+        print "One Singleton"
+
+class TestPairList(IMP.test.TestCase):
+    def setUp(self):
+        IMP.set_log_level(IMP.VERBOSE)
+
+    def test_it(self):
+        """Test the pair list restraint"""
+        m= IMP.Model()
+        ps0= IMP.Particles()
+        for i in range(0,10):
+            p= IMP.Particle()
+            m.add_particle(p)
+            ps0.append(p)
+        ps1= IMP.Particles()
+        for i in range(0,10):
+            p= IMP.Particle()
+            m.add_particle(p)
+            ps1.append(p)
+        os= IndexDiff()
+        s= IMP.PairChainRestraint(os)
+        s.add_chain(ps0)
+        s.add_chain(ps1)
+        m.add_restraint(s)
+        score= m.evaluate(False)
+        print str(score)
+        self.assertEqual(score, 18, "Wrong score")
+        s.clear_chains()
+        self.assertEqual(m.evaluate(False), 0, "Should be no terms")
+
+
+if __name__ == '__main__':
+    unittest.main()
Index: kernel/src/restraints/PairChainRestraint.cpp
===================================================================
--- kernel/src/restraints/PairChainRestraint.cpp	(revision 0)
+++ kernel/src/restraints/PairChainRestraint.cpp	(revision 0)
@@ -0,0 +1,85 @@
+/**
+ *  \file PairChainRestraint.cpp \brief Pair restraint.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#include "IMP/restraints/PairChainRestraint.h"
+#include "IMP/decorators/XYZDecorator.h"
+#include "IMP/Particle.h"
+#include "IMP/Model.h"
+#include "IMP/log.h"
+#include "IMP/Vector3D.h"
+#include "IMP/PairScore.h"
+
+#include <cmath>
+
+namespace IMP
+{
+
+PairChainRestraint::PairChainRestraint(PairScore* ts)
+{
+  ts_ = ts;
+  clear_chains();
+}
+
+void PairChainRestraint::add_chain(const Particles &ps)
+{
+  if (ps.size() <2) {
+    IMP_WARN("Adding a chain of length 1 or less to the AnglesRestraint"
+             << " doesn't accomplish anything."<< std::endl);
+  } else {
+    Restraint::add_particles(ps);
+    chain_splits_.back()= Restraint::number_of_particles();
+    chain_splits_.push_back(Restraint::number_of_particles());
+  }
+}
+
+Float PairChainRestraint::evaluate(DerivativeAccumulator *accum)
+{
+  int cur_break=0;
+  unsigned int i=1;
+  float score=0;
+  while (i < Restraint::number_of_particles()) {
+    /*IMP_LOG(VERBOSE, "Chain eval on " 
+            << Restraint::get_particle(i-2)->get_index()
+            << Restraint::get_particle(i-1)->get_index()
+            << Restraint::get_particle(i)->get_index()
+            << " split is " << chain_splits_[cur_break]
+            << std::endl);*/
+    score += ts_->evaluate(Restraint::get_particle(i-1),
+                           Restraint::get_particle(i),
+                           accum);
+    if (chain_splits_[cur_break] == i) {
+      i+=2;
+      ++cur_break;
+    } else {
+      ++i;
+    }
+  } 
+  return score;
+}
+
+void PairChainRestraint::clear_chains() {
+  Restraint::clear_particles();
+  chain_splits_.clear();
+  chain_splits_.push_back(0);
+}
+
+
+void PairChainRestraint::show(std::ostream& out) const
+{
+  if (get_is_active()) {
+    out << "Pair chain restraint (active):" << std::endl;
+  } else {
+    out << "Pair chain restraint (inactive):" << std::endl;
+  }
+
+  get_version_info().show(out);
+  out << "  " << chain_splits_.size()-1 << " chains" << std::endl;
+  ts_->show(out);
+  out << std::endl;
+}
+
+}  // namespace IMP
Index: kernel/include/IMP/restraints/PairChainRestraint.h
===================================================================
--- kernel/include/IMP/restraints/PairChainRestraint.h	(revision 0)
+++ kernel/include/IMP/restraints/PairChainRestraint.h	(revision 0)
@@ -0,0 +1,53 @@
+/**
+ *  \file PairChainRestraint.h   
+ *   \brief Restraint triplets of particles in chains.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#ifndef __IMP_PAIR_CHAIN_RESTRAINT_H
+#define __IMP_PAIR_CHAIN_RESTRAINT_H
+
+#include "../IMP_config.h"
+#include "../Restraint.h"
+#include "../internal/kernel_version_info.h"
+#include "../internal/ObjectPointer.h"
+
+#include <vector>
+
+namespace IMP
+{
+
+class PairScore;
+
+//! Restrain each pair of consecutive particles in each chain.
+/** \ingroup restraint
+ */
+class IMPDLLEXPORT PairChainRestraint : public Restraint
+{
+public:
+  //! Create the pair restraint.
+  /** \param[in] pair_score Pair score to apply.
+   */
+  PairChainRestraint(PairScore* pair_score);
+  virtual ~PairChainRestraint(){}
+
+  IMP_RESTRAINT(internal::kernel_version_info)
+
+  //! Add a chain of particles
+  /** Each two successive particles are restrained.
+   */
+  void add_chain(const Particles &ps);
+
+  //! Clear all the stored chains
+  void clear_chains();
+
+protected:
+  internal::ObjectPointer<PairScore, true> ts_;
+  std::vector<unsigned int> chain_splits_;
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_PAIR_CHAIN_RESTRAINT_H */