code: function constrainedMDSLayout(areas, params) {
          params = params || {};
          var restarts = params.restarts || 10;
  
          // bidirectionally map sets to a rowid  (so we can create a matrix)
          var sets = [],
              setids = {},
              i;
          for (i = 0; i < areas.length; ++i) {
              var area = areas[i];
              if (area.sets.length == 1) {
                  setids[area.sets[0]] = sets.length;
                  sets.push(area);
              }
          }
  
          var matrices = getDistanceMatrices(areas, sets, setids),
              distances = matrices.distances,
              constraints = matrices.constraints;
  
          // keep distances bounded, things get messed up otherwise.
          // TODO: proper preconditioner?
          var norm = norm2(distances.map(norm2)) / distances.length;
          distances = distances.map(function (row) {
              return row.map(function (value) {
                  return value / norm;
              });
          });
  
          var obj = function obj(x, fxprime) {
              return constrainedMDSGradient(x, fxprime, distances, constraints);
          };
  
          var best, current;
          for (i = 0; i < restarts; ++i) {
              var initial = zeros(distances.length * 2).map(Math.random);
  
              current = conjugateGradient(obj, initial, params);
              if (!best || current.fx < best.fx) {
                  best = current;
              }
          }
          var positions = best.x;
  
          // translate rows back to (x,y,radius) coordinates
          var circles = {};
          for (i = 0; i < sets.length; ++i) {
              var set = sets[i];
              circles[set.sets[0]] = {
                  x: positions[2 * i] * norm,
                  y: positions[2 * i + 1] * norm,
                  radius: Math.sqrt(set.size / Math.PI)
              };
          }
  
          if (params.history) {
              for (i = 0; i < params.history.length; ++i) {
                  scale(params.history[i].x, norm);
              }
          }
          return circles;
      }
docs: / use the constrained MDS variant to generate an initial layout