Add Program::ToString() to aid debugging.

Change-Id: I0ab37ed2fe0947ca87a152919d4e7dc9b56dedc6
diff --git a/internal/ceres/program.cc b/internal/ceres/program.cc
index 4dfb3a1..04248e7 100644
--- a/internal/ceres/program.cc
+++ b/internal/ceres/program.cc
@@ -216,5 +216,16 @@
   return max_residuals;
 }
 
+string Program::ToString() const {
+  string ret = "Program dump\n";
+  ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks());
+  ret += StringPrintf("Number of parameters: %d\n", NumParameters());
+  ret += "Parameters:\n";
+  for (int i = 0; i < parameter_blocks_.size(); ++i) {
+    ret += StringPrintf("%d: %s\n",
+                        i, parameter_blocks_[i]->ToString().c_str());
+  }
+}
+
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/program.h b/internal/ceres/program.h
index 7ae7db9..5002b7e 100644
--- a/internal/ceres/program.h
+++ b/internal/ceres/program.h
@@ -31,6 +31,7 @@
 #ifndef CERES_INTERNAL_PROGRAM_H_
 #define CERES_INTERNAL_PROGRAM_H_
 
+#include <string>
 #include <vector>
 #include "ceres/internal/port.h"
 
@@ -110,6 +111,10 @@
   int MaxParametersPerResidualBlock() const;
   int MaxResidualsPerResidualBlock() const;
 
+  // A human-readable dump of the parameter blocks for debugging.
+  // TODO(keir): If necessary, also dump the residual blocks.
+  string ToString() const;
+
  private:
   // The Program does not own the ParameterBlock or ResidualBlock objects.
   vector<ParameterBlock*> parameter_blocks_;