]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/graph/kamada_kawai_spring_layout.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / graph / kamada_kawai_spring_layout.hpp
index b10ebe3dc80016d8eb723f344886179879d8e5cf..148ebd9ee9ab3f63e9681f23544edbb1a9903c00 100644 (file)
 #include <boost/limits.hpp>
 #include <boost/config/no_tr1/cmath.hpp>
 
-namespace boost {
-  namespace detail { namespace graph {
-    /**
-     * Denotes an edge or display area side length used to scale a
-     * Kamada-Kawai drawing.
-     */
-    template<bool Edge, typename T>
-    struct edge_or_side
+namespace boost
+{
+namespace detail
+{
+    namespace graph
     {
-      explicit edge_or_side(T value) : value(value) {}
-
-      T value;
-    };
-
-    /**
-     * Compute the edge length from an edge length. This is trivial.
-     */
-    template<typename Graph, typename DistanceMap, typename IndexMap, 
-             typename T>
-    T compute_edge_length(const Graph&, DistanceMap, IndexMap, 
-                          edge_or_side<true, T> length)
-    { return length.value; }
-
-    /**
-     * Compute the edge length based on the display area side
-       length. We do this by dividing the side length by the largest
-       shortest distance between any two vertices in the graph.
-     */
-    template<typename Graph, typename DistanceMap, typename IndexMap, 
-             typename T>
-    T
-    compute_edge_length(const Graph& g, DistanceMap distance, IndexMap index,
-                        edge_or_side<false, T> length)
-    {
-      T result(0);
-
-      typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
-
-      for (vertex_iterator ui = vertices(g).first, end = vertices(g).second;
-           ui != end; ++ui) {
-        vertex_iterator vi = ui;
-        for (++vi; vi != end; ++vi) {
-          T dij = distance[get(index, *ui)][get(index, *vi)];
-          if (dij > result) result = dij;
+        /**
+         * Denotes an edge or display area side length used to scale a
+         * Kamada-Kawai drawing.
+         */
+        template < bool Edge, typename T > struct edge_or_side
+        {
+            explicit edge_or_side(T value) : value(value) {}
+
+            T value;
+        };
+
+        /**
+         * Compute the edge length from an edge length. This is trivial.
+         */
+        template < typename Graph, typename DistanceMap, typename IndexMap,
+            typename T >
+        T compute_edge_length(
+            const Graph&, DistanceMap, IndexMap, edge_or_side< true, T > length)
+        {
+            return length.value;
         }
-      }
-      return length.value / result;
-    }
 
-    /**
-     * Dense linear solver for fixed-size matrices.
-     */
-    template <std::size_t Size>
-    struct linear_solver {
-      // Indices in mat are (row, column)
-      // template <typename Vec>
-      // static Vec solve(double mat[Size][Size], Vec rhs);
-    };
-
-    template <>
-    struct linear_solver<1> {
-      template <typename Vec>
-      static Vec solve(double mat[1][1], Vec rhs) {
-        return rhs / mat[0][0];
-      }
-    };
-
-    // These are from http://en.wikipedia.org/wiki/Cramer%27s_rule
-    template <>
-    struct linear_solver<2> {
-      template <typename Vec>
-      static Vec solve(double mat[2][2], Vec rhs) {
-        double denom = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
-        double x_num = rhs[0]    * mat[1][1] - rhs[1]    * mat[0][1];
-        double y_num = mat[0][0] * rhs[1]    - mat[1][0] * rhs[0]   ;
-        Vec result;
-        result[0] = x_num / denom;
-        result[1] = y_num / denom;
-        return result;
-      }
-    };
-
-    template <>
-    struct linear_solver<3> {
-      template <typename Vec>
-      static Vec solve(double mat[3][3], Vec rhs) {
-        double denom = mat[0][0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2])
-                     - mat[1][0] * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2])
-                     + mat[2][0] * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]);
-        double x_num = rhs[0]    * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2])
-                     - rhs[1]    * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2])
-                     + rhs[2]    * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]);
-        double y_num = mat[0][0] * (rhs[1]    * mat[2][2] - rhs[2]    * mat[1][2])
-                     - mat[1][0] * (rhs[0]    * mat[2][2] - rhs[2]    * mat[0][2])
-                     + mat[2][0] * (rhs[0]    * mat[1][2] - rhs[1]    * mat[0][2]);
-        double z_num = mat[0][0] * (mat[1][1] * rhs[2]    - mat[2][1] * rhs[1]   )
-                     - mat[1][0] * (mat[0][1] * rhs[2]    - mat[2][1] * rhs[0]   )
-                     + mat[2][0] * (mat[0][1] * rhs[1]    - mat[1][1] * rhs[0]   );
-        Vec result;
-        result[0] = x_num / denom;
-        result[1] = y_num / denom;
-        result[2] = z_num / denom;
-        return result;
-      }
-    };
-
-    /**
-     * Implementation of the Kamada-Kawai spring layout algorithm.
-     */
-    template<typename Topology, typename Graph, typename PositionMap, typename WeightMap,
-             typename EdgeOrSideLength, typename Done,
-             typename VertexIndexMap, typename DistanceMatrix,
-             typename SpringStrengthMatrix, typename PartialDerivativeMap>
-    struct kamada_kawai_spring_layout_impl
-    {
-      typedef typename property_traits<WeightMap>::value_type weight_type;
-      typedef typename Topology::point_type Point;
-      typedef typename Topology::point_difference_type point_difference_type;
-      typedef point_difference_type deriv_type;
-      typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
-      typedef typename graph_traits<Graph>::vertex_descriptor
-        vertex_descriptor;
-
-      kamada_kawai_spring_layout_impl(
-        const Topology& topology,
-        const Graph& g, 
-        PositionMap position,
-        WeightMap weight, 
-        EdgeOrSideLength edge_or_side_length,
-        Done done,
-        weight_type spring_constant,
-        VertexIndexMap index,
-        DistanceMatrix distance,
-        SpringStrengthMatrix spring_strength,
-        PartialDerivativeMap partial_derivatives)
-        : topology(topology), g(g), position(position), weight(weight), 
-          edge_or_side_length(edge_or_side_length), done(done),
-          spring_constant(spring_constant), index(index), distance(distance),
-          spring_strength(spring_strength), 
-          partial_derivatives(partial_derivatives) {}
-
-      // Compute contribution of vertex i to the first partial
-      // derivatives (dE/dx_m, dE/dy_m) (for vertex m)
-      deriv_type
-      compute_partial_derivative(vertex_descriptor m, vertex_descriptor i)
-      {
-#ifndef BOOST_NO_STDC_NAMESPACE
-        using std::sqrt;
-#endif // BOOST_NO_STDC_NAMESPACE
-
-        deriv_type result;
-        if (i != m) {
-          point_difference_type diff = topology.difference(position[m], position[i]);
-          weight_type dist = topology.norm(diff);
-          result = spring_strength[get(index, m)][get(index, i)] 
-            * (diff - distance[get(index, m)][get(index, i)]/dist*diff);
+        /**
+         * Compute the edge length based on the display area side
+           length. We do this by dividing the side length by the largest
+           shortest distance between any two vertices in the graph.
+         */
+        template < typename Graph, typename DistanceMap, typename IndexMap,
+            typename T >
+        T compute_edge_length(const Graph& g, DistanceMap distance,
+            IndexMap index, edge_or_side< false, T > length)
+        {
+            T result(0);
+
+            typedef
+                typename graph_traits< Graph >::vertex_iterator vertex_iterator;
+
+            for (vertex_iterator ui = vertices(g).first,
+                                 end = vertices(g).second;
+                 ui != end; ++ui)
+            {
+                vertex_iterator vi = ui;
+                for (++vi; vi != end; ++vi)
+                {
+                    T dij = distance[get(index, *ui)][get(index, *vi)];
+                    if (dij > result)
+                        result = dij;
+                }
+            }
+            return length.value / result;
         }
 
-        return result;
-      }
+        /**
+         * Dense linear solver for fixed-size matrices.
+         */
+        template < std::size_t Size > struct linear_solver
+        {
+            // Indices in mat are (row, column)
+            // template <typename Vec>
+            // static Vec solve(double mat[Size][Size], Vec rhs);
+        };
+
+        template <> struct linear_solver< 1 >
+        {
+            template < typename Vec >
+            static Vec solve(double mat[1][1], Vec rhs)
+            {
+                return rhs / mat[0][0];
+            }
+        };
+
+        // These are from http://en.wikipedia.org/wiki/Cramer%27s_rule
+        template <> struct linear_solver< 2 >
+        {
+            template < typename Vec >
+            static Vec solve(double mat[2][2], Vec rhs)
+            {
+                double denom = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
+                double x_num = rhs[0] * mat[1][1] - rhs[1] * mat[0][1];
+                double y_num = mat[0][0] * rhs[1] - mat[1][0] * rhs[0];
+                Vec result;
+                result[0] = x_num / denom;
+                result[1] = y_num / denom;
+                return result;
+            }
+        };
+
+        template <> struct linear_solver< 3 >
+        {
+            template < typename Vec >
+            static Vec solve(double mat[3][3], Vec rhs)
+            {
+                double denom = mat[0][0]
+                        * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2])
+                    - mat[1][0]
+                        * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2])
+                    + mat[2][0]
+                        * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]);
+                double x_num
+                    = rhs[0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2])
+                    - rhs[1] * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2])
+                    + rhs[2] * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]);
+                double y_num
+                    = mat[0][0] * (rhs[1] * mat[2][2] - rhs[2] * mat[1][2])
+                    - mat[1][0] * (rhs[0] * mat[2][2] - rhs[2] * mat[0][2])
+                    + mat[2][0] * (rhs[0] * mat[1][2] - rhs[1] * mat[0][2]);
+                double z_num
+                    = mat[0][0] * (mat[1][1] * rhs[2] - mat[2][1] * rhs[1])
+                    - mat[1][0] * (mat[0][1] * rhs[2] - mat[2][1] * rhs[0])
+                    + mat[2][0] * (mat[0][1] * rhs[1] - mat[1][1] * rhs[0]);
+                Vec result;
+                result[0] = x_num / denom;
+                result[1] = y_num / denom;
+                result[2] = z_num / denom;
+                return result;
+            }
+        };
+
+        /**
+         * Implementation of the Kamada-Kawai spring layout algorithm.
+         */
+        template < typename Topology, typename Graph, typename PositionMap,
+            typename WeightMap, typename EdgeOrSideLength, typename Done,
+            typename VertexIndexMap, typename DistanceMatrix,
+            typename SpringStrengthMatrix, typename PartialDerivativeMap >
+        struct kamada_kawai_spring_layout_impl
+        {
+            typedef
+                typename property_traits< WeightMap >::value_type weight_type;
+            typedef typename Topology::point_type Point;
+            typedef
+                typename Topology::point_difference_type point_difference_type;
+            typedef point_difference_type deriv_type;
+            typedef
+                typename graph_traits< Graph >::vertex_iterator vertex_iterator;
+            typedef typename graph_traits< Graph >::vertex_descriptor
+                vertex_descriptor;
+
+            kamada_kawai_spring_layout_impl(const Topology& topology,
+                const Graph& g, PositionMap position, WeightMap weight,
+                EdgeOrSideLength edge_or_side_length, Done done,
+                weight_type spring_constant, VertexIndexMap index,
+                DistanceMatrix distance, SpringStrengthMatrix spring_strength,
+                PartialDerivativeMap partial_derivatives)
+            : topology(topology)
+            , g(g)
+            , position(position)
+            , weight(weight)
+            , edge_or_side_length(edge_or_side_length)
+            , done(done)
+            , spring_constant(spring_constant)
+            , index(index)
+            , distance(distance)
+            , spring_strength(spring_strength)
+            , partial_derivatives(partial_derivatives)
+            {
+            }
 
-      // Compute partial derivatives dE/dx_m and dE/dy_m
-      deriv_type 
-      compute_partial_derivatives(vertex_descriptor m)
-      {
+            // Compute contribution of vertex i to the first partial
+            // derivatives (dE/dx_m, dE/dy_m) (for vertex m)
+            deriv_type compute_partial_derivative(
+                vertex_descriptor m, vertex_descriptor i)
+            {
 #ifndef BOOST_NO_STDC_NAMESPACE
-        using std::sqrt;
+                using std::sqrt;
 #endif // BOOST_NO_STDC_NAMESPACE
 
-        deriv_type result;
-
-        // TBD: looks like an accumulate to me
-        BGL_FORALL_VERTICES_T(i, g, Graph) {
-          deriv_type deriv = compute_partial_derivative(m, i);
-          result += deriv;
-        }
+                deriv_type result;
+                if (i != m)
+                {
+                    point_difference_type diff
+                        = topology.difference(position[m], position[i]);
+                    weight_type dist = topology.norm(diff);
+                    result = spring_strength[get(index, m)][get(index, i)]
+                        * (diff
+                            - distance[get(index, m)][get(index, i)] / dist
+                                * diff);
+                }
 
-        return result;
-      }
+                return result;
+            }
 
-      // The actual Kamada-Kawai spring layout algorithm implementation
-      bool run()
-      {
+            // Compute partial derivatives dE/dx_m and dE/dy_m
+            deriv_type compute_partial_derivatives(vertex_descriptor m)
+            {
 #ifndef BOOST_NO_STDC_NAMESPACE
-        using std::sqrt;
+                using std::sqrt;
 #endif // BOOST_NO_STDC_NAMESPACE
 
-        // Compute d_{ij} and place it in the distance matrix
-        if (!johnson_all_pairs_shortest_paths(g, distance, index, weight, 
-                                              weight_type(0)))
-          return false;
-
-        // Compute L based on side length (if needed), or retrieve L
-        weight_type edge_length = 
-          detail::graph::compute_edge_length(g, distance, index,
-                                             edge_or_side_length);
-
-        // std::cerr << "edge_length = " << edge_length << std::endl;
-        
-        // Compute l_{ij} and k_{ij}
-        const weight_type K = spring_constant;
-        vertex_iterator ui, end;
-        for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) {
-          vertex_iterator vi = ui;
-          for (++vi; vi != end; ++vi) {
-            weight_type dij = distance[get(index, *ui)][get(index, *vi)];
-            if (dij == (std::numeric_limits<weight_type>::max)())
-              return false;
-            distance[get(index, *ui)][get(index, *vi)] = edge_length * dij;
-            distance[get(index, *vi)][get(index, *ui)] = edge_length * dij;
-            spring_strength[get(index, *ui)][get(index, *vi)] = K/(dij*dij);
-            spring_strength[get(index, *vi)][get(index, *ui)] = K/(dij*dij);
-          }
-        }
-        
-        // Compute Delta_i and find max
-        vertex_descriptor p = *vertices(g).first;
-        weight_type delta_p(0);
+                deriv_type result;
 
-        for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) {
-          deriv_type deriv = compute_partial_derivatives(*ui);
-          put(partial_derivatives, *ui, deriv);
+                // TBD: looks like an accumulate to me
+                BGL_FORALL_VERTICES_T(i, g, Graph)
+                {
+                    deriv_type deriv = compute_partial_derivative(m, i);
+                    result += deriv;
+                }
 
-          weight_type delta = topology.norm(deriv);
+                return result;
+            }
 
-          if (delta > delta_p) {
-            p = *ui;
-            delta_p = delta;
-          }
-        }
+            // The actual Kamada-Kawai spring layout algorithm implementation
+            bool run()
+            {
+#ifndef BOOST_NO_STDC_NAMESPACE
+                using std::sqrt;
+#endif // BOOST_NO_STDC_NAMESPACE
 
-        while (!done(delta_p, p, g, true)) {
-          // The contribution p makes to the partial derivatives of
-          // each vertex. Computing this (at O(n) cost) allows us to
-          // update the delta_i values in O(n) time instead of O(n^2)
-          // time.
-          std::vector<deriv_type> p_partials(num_vertices(g));
-          for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) {
-            vertex_descriptor i = *ui;
-            p_partials[get(index, i)] = compute_partial_derivative(i, p);
-          }
-
-          do {
-            // For debugging, compute the energy value E
-            double E = 0.;
-            for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) {
-              vertex_iterator vi = ui;
-              for (++vi; vi != end; ++vi) {
-                double dist = topology.distance(position[*ui], position[*vi]);
-                weight_type k_ij = spring_strength[get(index,*ui)][get(index,*vi)];
-                weight_type l_ij = distance[get(index, *ui)][get(index, *vi)];
-                E += .5 * k_ij * (dist - l_ij) * (dist - l_ij);
-              }
-            }
-            // std::cerr << "E = " << E << std::endl;
-
-            // Compute the elements of the Jacobian
-            // From
-            // http://www.cs.panam.edu/~rfowler/papers/1994_kumar_fowler_A_Spring_UTPACSTR.pdf
-            // with the bugs fixed in the off-diagonal case
-            weight_type dE_d_d[Point::dimensions][Point::dimensions];
-            for (std::size_t i = 0; i < Point::dimensions; ++i)
-              for (std::size_t j = 0; j < Point::dimensions; ++j)
-                dE_d_d[i][j] = 0.;
-            for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) {
-              vertex_descriptor i = *ui;
-              if (i != p) {
-                point_difference_type diff = topology.difference(position[p], position[i]);
-                weight_type dist = topology.norm(diff);
-                weight_type dist_squared = dist * dist;
-                weight_type inv_dist_cubed = 1. / (dist_squared * dist);
-                weight_type k_mi = spring_strength[get(index,p)][get(index,i)];
-                weight_type l_mi = distance[get(index, p)][get(index, i)];
-                for (std::size_t i = 0; i < Point::dimensions; ++i) {
-                  for (std::size_t j = 0; j < Point::dimensions; ++j) {
-                    if (i == j) {
-                      dE_d_d[i][i] += k_mi * (1 + (l_mi * (diff[i] * diff[i] - dist_squared) * inv_dist_cubed));
-                    } else {
-                      dE_d_d[i][j] += k_mi * l_mi * diff[i] * diff[j] * inv_dist_cubed;
-                      // dE_d_d[i][j] += k_mi * l_mi * sqrt(hypot(diff[i], diff[j])) * inv_dist_cubed;
+                // Compute d_{ij} and place it in the distance matrix
+                if (!johnson_all_pairs_shortest_paths(
+                        g, distance, index, weight, weight_type(0)))
+                    return false;
+
+                // Compute L based on side length (if needed), or retrieve L
+                weight_type edge_length = detail::graph::compute_edge_length(
+                    g, distance, index, edge_or_side_length);
+
+                // std::cerr << "edge_length = " << edge_length << std::endl;
+
+                // Compute l_{ij} and k_{ij}
+                const weight_type K = spring_constant;
+                vertex_iterator ui, end;
+                for (ui = vertices(g).first, end = vertices(g).second;
+                     ui != end; ++ui)
+                {
+                    vertex_iterator vi = ui;
+                    for (++vi; vi != end; ++vi)
+                    {
+                        weight_type dij
+                            = distance[get(index, *ui)][get(index, *vi)];
+                        if (dij == (std::numeric_limits< weight_type >::max)())
+                            return false;
+                        distance[get(index, *ui)][get(index, *vi)]
+                            = edge_length * dij;
+                        distance[get(index, *vi)][get(index, *ui)]
+                            = edge_length * dij;
+                        spring_strength[get(index, *ui)][get(index, *vi)]
+                            = K / (dij * dij);
+                        spring_strength[get(index, *vi)][get(index, *ui)]
+                            = K / (dij * dij);
                     }
-                  }
                 }
-              }
-            }
-
-            deriv_type dE_d = get(partial_derivatives, p);
 
-            // Solve dE_d_d * delta = -dE_d to get delta
-            point_difference_type delta = -linear_solver<Point::dimensions>::solve(dE_d_d, dE_d);
+                // Compute Delta_i and find max
+                vertex_descriptor p = *vertices(g).first;
+                weight_type delta_p(0);
 
-            // Move p by delta
-            position[p] = topology.adjust(position[p], delta);
+                for (ui = vertices(g).first, end = vertices(g).second;
+                     ui != end; ++ui)
+                {
+                    deriv_type deriv = compute_partial_derivatives(*ui);
+                    put(partial_derivatives, *ui, deriv);
 
-            // Recompute partial derivatives and delta_p
-            deriv_type deriv = compute_partial_derivatives(p);
-            put(partial_derivatives, p, deriv);
+                    weight_type delta = topology.norm(deriv);
 
-            delta_p = topology.norm(deriv);
-          } while (!done(delta_p, p, g, false));
-
-          // Select new p by updating each partial derivative and delta
-          vertex_descriptor old_p = p;
-          for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) {
-            deriv_type old_deriv_p = p_partials[get(index, *ui)];
-            deriv_type old_p_partial = 
-              compute_partial_derivative(*ui, old_p);
-            deriv_type deriv = get(partial_derivatives, *ui);
+                    if (delta > delta_p)
+                    {
+                        p = *ui;
+                        delta_p = delta;
+                    }
+                }
 
-            deriv += old_p_partial - old_deriv_p;
+                while (!done(delta_p, p, g, true))
+                {
+                    // The contribution p makes to the partial derivatives of
+                    // each vertex. Computing this (at O(n) cost) allows us to
+                    // update the delta_i values in O(n) time instead of O(n^2)
+                    // time.
+                    std::vector< deriv_type > p_partials(num_vertices(g));
+                    for (ui = vertices(g).first, end = vertices(g).second;
+                         ui != end; ++ui)
+                    {
+                        vertex_descriptor i = *ui;
+                        p_partials[get(index, i)]
+                            = compute_partial_derivative(i, p);
+                    }
 
-            put(partial_derivatives, *ui, deriv);
-            weight_type delta = topology.norm(deriv);
+                    do
+                    {
+                        // For debugging, compute the energy value E
+                        double E = 0.;
+                        for (ui = vertices(g).first, end = vertices(g).second;
+                             ui != end; ++ui)
+                        {
+                            vertex_iterator vi = ui;
+                            for (++vi; vi != end; ++vi)
+                            {
+                                double dist = topology.distance(
+                                    position[*ui], position[*vi]);
+                                weight_type k_ij = spring_strength[get(
+                                    index, *ui)][get(index, *vi)];
+                                weight_type l_ij = distance[get(index, *ui)]
+                                                           [get(index, *vi)];
+                                E += .5 * k_ij * (dist - l_ij) * (dist - l_ij);
+                            }
+                        }
+                        // std::cerr << "E = " << E << std::endl;
+
+                        // Compute the elements of the Jacobian
+                        // From
+                        // http://www.cs.panam.edu/~rfowler/papers/1994_kumar_fowler_A_Spring_UTPACSTR.pdf
+                        // with the bugs fixed in the off-diagonal case
+                        weight_type dE_d_d[Point::dimensions]
+                                          [Point::dimensions];
+                        for (std::size_t i = 0; i < Point::dimensions; ++i)
+                            for (std::size_t j = 0; j < Point::dimensions; ++j)
+                                dE_d_d[i][j] = 0.;
+                        for (ui = vertices(g).first, end = vertices(g).second;
+                             ui != end; ++ui)
+                        {
+                            vertex_descriptor i = *ui;
+                            if (i != p)
+                            {
+                                point_difference_type diff
+                                    = topology.difference(
+                                        position[p], position[i]);
+                                weight_type dist = topology.norm(diff);
+                                weight_type dist_squared = dist * dist;
+                                weight_type inv_dist_cubed
+                                    = 1. / (dist_squared * dist);
+                                weight_type k_mi = spring_strength[get(
+                                    index, p)][get(index, i)];
+                                weight_type l_mi
+                                    = distance[get(index, p)][get(index, i)];
+                                for (std::size_t i = 0; i < Point::dimensions;
+                                     ++i)
+                                {
+                                    for (std::size_t j = 0;
+                                         j < Point::dimensions; ++j)
+                                    {
+                                        if (i == j)
+                                        {
+                                            dE_d_d[i][i] += k_mi
+                                                * (1
+                                                    + (l_mi
+                                                        * (diff[i] * diff[i]
+                                                            - dist_squared)
+                                                        * inv_dist_cubed));
+                                        }
+                                        else
+                                        {
+                                            dE_d_d[i][j] += k_mi * l_mi
+                                                * diff[i] * diff[j]
+                                                * inv_dist_cubed;
+                                            // dE_d_d[i][j] += k_mi * l_mi *
+                                            // sqrt(hypot(diff[i], diff[j])) *
+                                            // inv_dist_cubed;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        deriv_type dE_d = get(partial_derivatives, p);
+
+                        // Solve dE_d_d * delta = -dE_d to get delta
+                        point_difference_type delta
+                            = -linear_solver< Point::dimensions >::solve(
+                                dE_d_d, dE_d);
+
+                        // Move p by delta
+                        position[p] = topology.adjust(position[p], delta);
+
+                        // Recompute partial derivatives and delta_p
+                        deriv_type deriv = compute_partial_derivatives(p);
+                        put(partial_derivatives, p, deriv);
+
+                        delta_p = topology.norm(deriv);
+                    } while (!done(delta_p, p, g, false));
+
+                    // Select new p by updating each partial derivative and
+                    // delta
+                    vertex_descriptor old_p = p;
+                    for (ui = vertices(g).first, end = vertices(g).second;
+                         ui != end; ++ui)
+                    {
+                        deriv_type old_deriv_p = p_partials[get(index, *ui)];
+                        deriv_type old_p_partial
+                            = compute_partial_derivative(*ui, old_p);
+                        deriv_type deriv = get(partial_derivatives, *ui);
+
+                        deriv += old_p_partial - old_deriv_p;
+
+                        put(partial_derivatives, *ui, deriv);
+                        weight_type delta = topology.norm(deriv);
+
+                        if (delta > delta_p)
+                        {
+                            p = *ui;
+                            delta_p = delta;
+                        }
+                    }
+                }
 
-            if (delta > delta_p) {
-              p = *ui;
-              delta_p = delta;
+                return true;
             }
-          }
-        }
 
-        return true;
-      }
-
-      const Topology& topology;
-      const Graph& g; 
-      PositionMap position;
-      WeightMap weight; 
-      EdgeOrSideLength edge_or_side_length;
-      Done done;
-      weight_type spring_constant;
-      VertexIndexMap index;
-      DistanceMatrix distance;
-      SpringStrengthMatrix spring_strength;
-      PartialDerivativeMap partial_derivatives;
-    };
-  } } // end namespace detail::graph
-
-  /// States that the given quantity is an edge length.
-  template<typename T> 
-  inline detail::graph::edge_or_side<true, T>
-  edge_length(T x) 
-  { return detail::graph::edge_or_side<true, T>(x); }
-
-  /// States that the given quantity is a display area side length.
-  template<typename T> 
-  inline detail::graph::edge_or_side<false, T>
-  side_length(T x) 
-  { return detail::graph::edge_or_side<false, T>(x); }
-
-  /** 
-   * \brief Determines when to terminate layout of a particular graph based
-   * on a given relative tolerance. 
-   */
-  template<typename T = double>
-  struct layout_tolerance
-  {
+            const Topology& topology;
+            const Graph& g;
+            PositionMap position;
+            WeightMap weight;
+            EdgeOrSideLength edge_or_side_length;
+            Done done;
+            weight_type spring_constant;
+            VertexIndexMap index;
+            DistanceMatrix distance;
+            SpringStrengthMatrix spring_strength;
+            PartialDerivativeMap partial_derivatives;
+        };
+    }
+} // end namespace detail::graph
+
+/// States that the given quantity is an edge length.
+template < typename T >
+inline detail::graph::edge_or_side< true, T > edge_length(T x)
+{
+    return detail::graph::edge_or_side< true, T >(x);
+}
+
+/// States that the given quantity is a display area side length.
+template < typename T >
+inline detail::graph::edge_or_side< false, T > side_length(T x)
+{
+    return detail::graph::edge_or_side< false, T >(x);
+}
+
+/**
+ * \brief Determines when to terminate layout of a particular graph based
+ * on a given relative tolerance.
+ */
+template < typename T = double > struct layout_tolerance
+{
     layout_tolerance(const T& tolerance = T(0.001))
-      : tolerance(tolerance), last_energy((std::numeric_limits<T>::max)()),
-        last_local_energy((std::numeric_limits<T>::max)()) { }
-
-    template<typename Graph>
-    bool 
-    operator()(T delta_p, 
-               typename boost::graph_traits<Graph>::vertex_descriptor p,
-               const Graph& g,
-               bool global)
+    : tolerance(tolerance)
+    , last_energy((std::numeric_limits< T >::max)())
+    , last_local_energy((std::numeric_limits< T >::max)())
+    {
+    }
+
+    template < typename Graph >
+    bool operator()(T delta_p,
+        typename boost::graph_traits< Graph >::vertex_descriptor p,
+        const Graph& g, bool global)
     {
-      if (global) {
-        if (last_energy == (std::numeric_limits<T>::max)()) {
-          last_energy = delta_p;
-          return false;
+        if (global)
+        {
+            if (last_energy == (std::numeric_limits< T >::max)())
+            {
+                last_energy = delta_p;
+                return false;
+            }
+
+            T diff = last_energy - delta_p;
+            if (diff < T(0))
+                diff = -diff;
+            bool done = (delta_p == T(0) || diff / last_energy < tolerance);
+            last_energy = delta_p;
+            return done;
         }
-          
-        T diff = last_energy - delta_p;
-        if (diff < T(0)) diff = -diff;
-        bool done = (delta_p == T(0) || diff / last_energy < tolerance);
-        last_energy = delta_p;
-        return done;
-      } else {
-        if (last_local_energy == (std::numeric_limits<T>::max)()) {
-          last_local_energy = delta_p;
-          return delta_p == T(0);
+        else
+        {
+            if (last_local_energy == (std::numeric_limits< T >::max)())
+            {
+                last_local_energy = delta_p;
+                return delta_p == T(0);
+            }
+
+            T diff = last_local_energy - delta_p;
+            bool done
+                = (delta_p == T(0) || (diff / last_local_energy) < tolerance);
+            last_local_energy = delta_p;
+            return done;
         }
-          
-        T diff = last_local_energy - delta_p;
-        bool done = (delta_p == T(0) || (diff / last_local_energy) < tolerance);
-        last_local_energy = delta_p;
-        return done;
-      }
     }
 
-  private:
+private:
     T tolerance;
     T last_energy;
     T last_local_energy;
-  };
-
-  /** \brief Kamada-Kawai spring layout for undirected graphs.
-   *
-   * This algorithm performs graph layout (in two dimensions) for
-   * connected, undirected graphs. It operates by relating the layout
-   * of graphs to a dynamic spring system and minimizing the energy
-   * within that system. The strength of a spring between two vertices
-   * is inversely proportional to the square of the shortest distance
-   * (in graph terms) between those two vertices. Essentially,
-   * vertices that are closer in the graph-theoretic sense (i.e., by
-   * following edges) will have stronger springs and will therefore be
-   * placed closer together.
-   *
-   * Prior to invoking this algorithm, it is recommended that the
-   * vertices be placed along the vertices of a regular n-sided
-   * polygon.
-   *
-   * \param g (IN) must be a model of Vertex List Graph, Edge List
-   * Graph, and Incidence Graph and must be undirected.
-   *
-   * \param position (OUT) must be a model of Lvalue Property Map,
-   * where the value type is a class containing fields @c x and @c y
-   * that will be set to the @c x and @c y coordinates of each vertex.
-   *
-   * \param weight (IN) must be a model of Readable Property Map,
-   * which provides the weight of each edge in the graph @p g.
-   *
-   * \param topology (IN) must be a topology object (see topology.hpp),
-   * which provides operations on points and differences between them.
-   *
-   * \param edge_or_side_length (IN) provides either the unit length
-   * @c e of an edge in the layout or the length of a side @c s of the
-   * display area, and must be either @c boost::edge_length(e) or @c
-   * boost::side_length(s), respectively.
-   *
-   * \param done (IN) is a 4-argument function object that is passed
-   * the current value of delta_p (i.e., the energy of vertex @p p),
-   * the vertex @p p, the graph @p g, and a boolean flag indicating
-   * whether @p delta_p is the maximum energy in the system (when @c
-   * true) or the energy of the vertex being moved. Defaults to @c
-   * layout_tolerance instantiated over the value type of the weight
-   * map.
-   *
-   * \param spring_constant (IN) is the constant multiplied by each
-   * spring's strength. Larger values create systems with more energy
-   * that can take longer to stabilize; smaller values create systems
-   * with less energy that stabilize quickly but do not necessarily
-   * result in pleasing layouts. The default value is 1.
-   *
-   * \param index (IN) is a mapping from vertices to index values
-   * between 0 and @c num_vertices(g). The default is @c
-   * get(vertex_index,g).
-   *
-   * \param distance (UTIL/OUT) will be used to store the distance
-   * from every vertex to every other vertex, which is computed in the
-   * first stages of the algorithm. This value's type must be a model
-   * of BasicMatrix with value type equal to the value type of the
-   * weight map. The default is a vector of vectors.
-   *
-   * \param spring_strength (UTIL/OUT) will be used to store the
-   * strength of the spring between every pair of vertices. This
-   * value's type must be a model of BasicMatrix with value type equal
-   * to the value type of the weight map. The default is a vector of
-   * vectors.
-   *
-   * \param partial_derivatives (UTIL) will be used to store the
-   * partial derivates of each vertex with respect to the @c x and @c
-   * y coordinates. This must be a Read/Write Property Map whose value
-   * type is a pair with both types equivalent to the value type of
-   * the weight map. The default is an iterator property map.
-   *
-   * \returns @c true if layout was successful or @c false if a
-   * negative weight cycle was detected.
-   */
-  template<typename Topology, typename Graph, typename PositionMap, typename WeightMap,
-           typename T, bool EdgeOrSideLength, typename Done,
-           typename VertexIndexMap, typename DistanceMatrix,
-           typename SpringStrengthMatrix, typename PartialDerivativeMap>
-  bool 
-  kamada_kawai_spring_layout(
-    const Graph& g, 
-    PositionMap position,
-    WeightMap weight, 
-    const Topology& topology,
-    detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
+};
+
+/** \brief Kamada-Kawai spring layout for undirected graphs.
+ *
+ * This algorithm performs graph layout (in two dimensions) for
+ * connected, undirected graphs. It operates by relating the layout
+ * of graphs to a dynamic spring system and minimizing the energy
+ * within that system. The strength of a spring between two vertices
+ * is inversely proportional to the square of the shortest distance
+ * (in graph terms) between those two vertices. Essentially,
+ * vertices that are closer in the graph-theoretic sense (i.e., by
+ * following edges) will have stronger springs and will therefore be
+ * placed closer together.
+ *
+ * Prior to invoking this algorithm, it is recommended that the
+ * vertices be placed along the vertices of a regular n-sided
+ * polygon.
+ *
+ * \param g (IN) must be a model of Vertex List Graph, Edge List
+ * Graph, and Incidence Graph and must be undirected.
+ *
+ * \param position (OUT) must be a model of Lvalue Property Map,
+ * where the value type is a class containing fields @c x and @c y
+ * that will be set to the @c x and @c y coordinates of each vertex.
+ *
+ * \param weight (IN) must be a model of Readable Property Map,
+ * which provides the weight of each edge in the graph @p g.
+ *
+ * \param topology (IN) must be a topology object (see topology.hpp),
+ * which provides operations on points and differences between them.
+ *
+ * \param edge_or_side_length (IN) provides either the unit length
+ * @c e of an edge in the layout or the length of a side @c s of the
+ * display area, and must be either @c boost::edge_length(e) or @c
+ * boost::side_length(s), respectively.
+ *
+ * \param done (IN) is a 4-argument function object that is passed
+ * the current value of delta_p (i.e., the energy of vertex @p p),
+ * the vertex @p p, the graph @p g, and a boolean flag indicating
+ * whether @p delta_p is the maximum energy in the system (when @c
+ * true) or the energy of the vertex being moved. Defaults to @c
+ * layout_tolerance instantiated over the value type of the weight
+ * map.
+ *
+ * \param spring_constant (IN) is the constant multiplied by each
+ * spring's strength. Larger values create systems with more energy
+ * that can take longer to stabilize; smaller values create systems
+ * with less energy that stabilize quickly but do not necessarily
+ * result in pleasing layouts. The default value is 1.
+ *
+ * \param index (IN) is a mapping from vertices to index values
+ * between 0 and @c num_vertices(g). The default is @c
+ * get(vertex_index,g).
+ *
+ * \param distance (UTIL/OUT) will be used to store the distance
+ * from every vertex to every other vertex, which is computed in the
+ * first stages of the algorithm. This value's type must be a model
+ * of BasicMatrix with value type equal to the value type of the
+ * weight map. The default is a vector of vectors.
+ *
+ * \param spring_strength (UTIL/OUT) will be used to store the
+ * strength of the spring between every pair of vertices. This
+ * value's type must be a model of BasicMatrix with value type equal
+ * to the value type of the weight map. The default is a vector of
+ * vectors.
+ *
+ * \param partial_derivatives (UTIL) will be used to store the
+ * partial derivates of each vertex with respect to the @c x and @c
+ * y coordinates. This must be a Read/Write Property Map whose value
+ * type is a pair with both types equivalent to the value type of
+ * the weight map. The default is an iterator property map.
+ *
+ * \returns @c true if layout was successful or @c false if a
+ * negative weight cycle was detected.
+ */
+template < typename Topology, typename Graph, typename PositionMap,
+    typename WeightMap, typename T, bool EdgeOrSideLength, typename Done,
+    typename VertexIndexMap, typename DistanceMatrix,
+    typename SpringStrengthMatrix, typename PartialDerivativeMap >
+bool kamada_kawai_spring_layout(const Graph& g, PositionMap position,
+    WeightMap weight, const Topology& topology,
+    detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length,
     Done done,
-    typename property_traits<WeightMap>::value_type spring_constant,
-    VertexIndexMap index,
-    DistanceMatrix distance,
+    typename property_traits< WeightMap >::value_type spring_constant,
+    VertexIndexMap index, DistanceMatrix distance,
     SpringStrengthMatrix spring_strength,
     PartialDerivativeMap partial_derivatives)
-  {
-    BOOST_STATIC_ASSERT((is_convertible<
-                           typename graph_traits<Graph>::directed_category*,
-                           undirected_tag*
-                         >::value));
-
-    detail::graph::kamada_kawai_spring_layout_impl<
-      Topology, Graph, PositionMap, WeightMap, 
-      detail::graph::edge_or_side<EdgeOrSideLength, T>, Done, VertexIndexMap, 
-      DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap>
-      alg(topology, g, position, weight, edge_or_side_length, done, spring_constant,
-          index, distance, spring_strength, partial_derivatives);
+{
+    BOOST_STATIC_ASSERT(
+        (is_convertible< typename graph_traits< Graph >::directed_category*,
+            undirected_tag* >::value));
+
+    detail::graph::kamada_kawai_spring_layout_impl< Topology, Graph,
+        PositionMap, WeightMap,
+        detail::graph::edge_or_side< EdgeOrSideLength, T >, Done,
+        VertexIndexMap, DistanceMatrix, SpringStrengthMatrix,
+        PartialDerivativeMap >
+        alg(topology, g, position, weight, edge_or_side_length, done,
+            spring_constant, index, distance, spring_strength,
+            partial_derivatives);
     return alg.run();
-  }
-
-  /**
-   * \overload
-   */
-  template<typename Topology, typename Graph, typename PositionMap, typename WeightMap,
-           typename T, bool EdgeOrSideLength, typename Done, 
-           typename VertexIndexMap>
-  bool 
-  kamada_kawai_spring_layout(
-    const Graph& g, 
-    PositionMap position,
-    WeightMap weight, 
-    const Topology& topology,
-    detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
+}
+
+/**
+ * \overload
+ */
+template < typename Topology, typename Graph, typename PositionMap,
+    typename WeightMap, typename T, bool EdgeOrSideLength, typename Done,
+    typename VertexIndexMap >
+bool kamada_kawai_spring_layout(const Graph& g, PositionMap position,
+    WeightMap weight, const Topology& topology,
+    detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length,
     Done done,
-    typename property_traits<WeightMap>::value_type spring_constant,
+    typename property_traits< WeightMap >::value_type spring_constant,
     VertexIndexMap index)
-  {
-    typedef typename property_traits<WeightMap>::value_type weight_type;
+{
+    typedef typename property_traits< WeightMap >::value_type weight_type;
 
-    typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
-    typedef std::vector<weight_type> weight_vec;
+    typename graph_traits< Graph >::vertices_size_type n = num_vertices(g);
+    typedef std::vector< weight_type > weight_vec;
 
-    std::vector<weight_vec> distance(n, weight_vec(n));
-    std::vector<weight_vec> spring_strength(n, weight_vec(n));
-    std::vector<typename Topology::point_difference_type> partial_derivatives(n);
+    std::vector< weight_vec > distance(n, weight_vec(n));
+    std::vector< weight_vec > spring_strength(n, weight_vec(n));
+    std::vector< typename Topology::point_difference_type > partial_derivatives(
+        n);
 
-    return 
-      kamada_kawai_spring_layout(
-        g, position, weight, topology, edge_or_side_length, done, spring_constant, index,
-        distance.begin(),
+    return kamada_kawai_spring_layout(g, position, weight, topology,
+        edge_or_side_length, done, spring_constant, index, distance.begin(),
         spring_strength.begin(),
         make_iterator_property_map(partial_derivatives.begin(), index,
-                                   typename Topology::point_difference_type()));
-  }
-
-  /**
-   * \overload
-   */
-  template<typename Topology, typename Graph, typename PositionMap, typename WeightMap,
-           typename T, bool EdgeOrSideLength, typename Done>
-  bool 
-  kamada_kawai_spring_layout(
-    const Graph& g, 
-    PositionMap position,
-    WeightMap weight, 
-    const Topology& topology,
-    detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
+            typename Topology::point_difference_type()));
+}
+
+/**
+ * \overload
+ */
+template < typename Topology, typename Graph, typename PositionMap,
+    typename WeightMap, typename T, bool EdgeOrSideLength, typename Done >
+bool kamada_kawai_spring_layout(const Graph& g, PositionMap position,
+    WeightMap weight, const Topology& topology,
+    detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length,
     Done done,
-    typename property_traits<WeightMap>::value_type spring_constant)
-  {
-    return kamada_kawai_spring_layout(g, position, weight, topology, edge_or_side_length,
-                                      done, spring_constant, 
-                                      get(vertex_index, g));
-  }
-
-  /**
-   * \overload
-   */
-  template<typename Topology, typename Graph, typename PositionMap, typename WeightMap,
-           typename T, bool EdgeOrSideLength, typename Done>
-  bool 
-  kamada_kawai_spring_layout(
-    const Graph& g, 
-    PositionMap position,
-    WeightMap weight, 
-    const Topology& topology,
-    detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
+    typename property_traits< WeightMap >::value_type spring_constant)
+{
+    return kamada_kawai_spring_layout(g, position, weight, topology,
+        edge_or_side_length, done, spring_constant, get(vertex_index, g));
+}
+
+/**
+ * \overload
+ */
+template < typename Topology, typename Graph, typename PositionMap,
+    typename WeightMap, typename T, bool EdgeOrSideLength, typename Done >
+bool kamada_kawai_spring_layout(const Graph& g, PositionMap position,
+    WeightMap weight, const Topology& topology,
+    detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length,
     Done done)
-  {
-    typedef typename property_traits<WeightMap>::value_type weight_type;
-    return kamada_kawai_spring_layout(g, position, weight, topology, edge_or_side_length,
-                                      done, weight_type(1)); 
-  }
-
-  /**
-   * \overload
-   */
-  template<typename Topology, typename Graph, typename PositionMap, typename WeightMap,
-           typename T, bool EdgeOrSideLength>
-  bool 
-  kamada_kawai_spring_layout(
-    const Graph& g, 
-    PositionMap position,
-    WeightMap weight, 
-    const Topology& topology,
-    detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length)
-  {
-    typedef typename property_traits<WeightMap>::value_type weight_type;
-    return kamada_kawai_spring_layout(g, position, weight, topology, edge_or_side_length,
-                                      layout_tolerance<weight_type>(),
-                                      weight_type(1.0), 
-                                      get(vertex_index, g));
-  }
+{
+    typedef typename property_traits< WeightMap >::value_type weight_type;
+    return kamada_kawai_spring_layout(g, position, weight, topology,
+        edge_or_side_length, done, weight_type(1));
+}
+
+/**
+ * \overload
+ */
+template < typename Topology, typename Graph, typename PositionMap,
+    typename WeightMap, typename T, bool EdgeOrSideLength >
+bool kamada_kawai_spring_layout(const Graph& g, PositionMap position,
+    WeightMap weight, const Topology& topology,
+    detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length)
+{
+    typedef typename property_traits< WeightMap >::value_type weight_type;
+    return kamada_kawai_spring_layout(g, position, weight, topology,
+        edge_or_side_length, layout_tolerance< weight_type >(),
+        weight_type(1.0), get(vertex_index, g));
+}
 } // end namespace boost
 
 #endif // BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP