00001 #include <TooN/TooN.h>
00002 #include <TooN/LU.h>
00003 #include <TooN/helpers.h>
00004 #include <TooN/gaussian_elimination.h>
00005 #include <TooN/gauss_jordan.h>
00006 #include <tr1/random>
00007 #include <sys/time.h>
00008 #include <vector>
00009 #include <utility>
00010 #include <string>
00011 #include <map>
00012 #include <algorithm>
00013 #include <iomanip>
00014
00015
00016 using namespace TooN;
00017 using namespace std;
00018 using namespace tr1;
00019
00020 double get_time_of_day()
00021 {
00022 struct timeval tv;
00023 gettimeofday(&tv,NULL);
00024 return tv.tv_sec+tv.tv_usec * 1e-6;
00025 }
00026
00027 std::tr1::mt19937 eng;
00028 std::tr1::uniform_real<double> rnd;
00029 double global_sum;
00030
00031 #include "solvers.cc"
00032
00033
00034 struct UseCompiledCramer
00035 {
00036 template<int R, int C> static void solve(const Matrix<R, R>& a, const Matrix<R, C>& b, Matrix<R, C>& x)
00037 {
00038 solve_direct(a, b, x);
00039 }
00040
00041 static string name()
00042 {
00043 return "CC";
00044 }
00045 };
00046
00047 struct UseLU
00048 {
00049 template<int R, int C> static void solve(const Matrix<R, R>& a, const Matrix<R, C>& b, Matrix<R, C>& x)
00050 {
00051 LU<R> lu(a);
00052
00053 x = lu.backsub(b);
00054 }
00055
00056 static string name()
00057 {
00058 return "LU";
00059 }
00060 };
00061
00062 struct UseLUInv
00063 {
00064 template<int R, int C> static void solve(const Matrix<R, R>& a, const Matrix<R, C>& b, Matrix<R, C>& x)
00065 {
00066 LU<R> lu(a);
00067
00068 x = lu.get_inverse() * b;
00069
00070 }
00071
00072 static string name()
00073 {
00074 return "LI";
00075 }
00076 };
00077
00078
00079 struct UseGaussianElimination
00080 {
00081 template<int R, int C> static void solve(const Matrix<R, R>& a, const Matrix<R, C>& b, Matrix<R, C>& x)
00082 {
00083 x = gaussian_elimination(a, b);
00084 }
00085
00086 static string name()
00087 {
00088 return "GE";
00089 }
00090 };
00091
00092 struct UseGaussianEliminationInverse
00093 {
00094 template<int R, int C> static void solve(const Matrix<R, R>& a, const Matrix<R, C>& b, Matrix<R, C>& x)
00095 {
00096 Matrix<R> i, inv;
00097 i = Identity;
00098 inv = gaussian_elimination(a, i);
00099 x = inv * b;
00100 }
00101
00102 static string name()
00103 {
00104 return "GI";
00105 }
00106 };
00107
00108 struct UseGaussJordanInverse
00109 {
00110 template<int R, int C> static void solve(const Matrix<R, R>& a, const Matrix<R, C>& b, Matrix<R, C>& x)
00111 {
00112 Matrix<R, 2*R> m;
00113 m.template slice<0,0,R,R>() = a;
00114 m.template slice<0,R,R,R>() = Identity;
00115 gauss_jordan(m);
00116 x = m.template slice<0,R,R,R>() * b;
00117 }
00118
00119 static string name()
00120 {
00121 return "GJ";
00122 }
00123 };
00124
00125
00126 template<int Size, int Cols, class Solver> void benchmark_ax_eq_b(map<string, vector<double> >& results)
00127 {
00128 double time=0, t_tmp, start = get_time_of_day(), t_tmp2;
00129 double sum=0;
00130 int n=0;
00131
00132 while(get_time_of_day() - start < .1)
00133 {
00134 Matrix<Size> a;
00135 for(int r=0; r < Size; r++)
00136 for(int c=0; c < Size; c++)
00137 a[r][c] = rnd(eng);
00138
00139
00140 Matrix<Size, Cols> b, x;
00141
00142 for(int r=0; r < Size; r++)
00143 for(int c=0; c < Cols; c++)
00144 b[r][c] = rnd(eng);
00145
00146 a[0][0] += (t_tmp=get_time_of_day()) * 1e-20;
00147 Solver::template solve<Size, Cols>(a, b, x);
00148 global_sum += (t_tmp2=get_time_of_day())*x[Size-1][Cols-1];
00149
00150 time += t_tmp2 - t_tmp;
00151 n++;
00152 }
00153
00154 results[Solver::name()].push_back(n/time);
00155
00156 global_sum += sum;
00157 }
00158
00159
00160
00161
00162 template<int Size, int Cols, typename Solver, bool Use> struct Optional
00163 {
00164 static void solve(map<string, vector<double> >& r)
00165 {
00166 benchmark_ax_eq_b<Size, Cols, Solver>(r);
00167 }
00168 };
00169
00170
00171 template<int Size, int Cols, typename Solver > struct Optional<Size, Cols, Solver, 0>
00172 {
00173 static void solve(map<string, vector<double> >&)
00174 {
00175 }
00176 };
00177
00178 template<int Size, int C=1, bool End=0> struct ColIter
00179 {
00180 static void iter()
00181 {
00182 static const int Lin = Size*2;
00183 static const int Grow = 1;
00184 static const int Cols = C + (C<=Lin?0:(C-Lin)*(C-Lin)*(C-Lin)/Grow);
00185 map<string, vector<double> > results;
00186 cout << Size << "\t" << Cols << "\t";
00187
00188
00189 for(int i=0; i < 10; i++)
00190 {
00191 benchmark_ax_eq_b<Size, Cols, UseGaussJordanInverse>(results);
00192 benchmark_ax_eq_b<Size, Cols, UseGaussianElimination>(results);
00193 benchmark_ax_eq_b<Size, Cols, UseGaussianEliminationInverse>(results);
00194 benchmark_ax_eq_b<Size, Cols, UseLUInv>(results);
00195 benchmark_ax_eq_b<Size, Cols, UseLU>(results);
00196 Optional<Size, Cols, UseCompiledCramer, (Size<=highest_solver)>::solve(results);
00197 }
00198
00199 vector<pair<double, string> > res;
00200 for(map<string, vector<double> >::iterator i=results.begin(); i != results.end(); i++)
00201 {
00202 sort(i->second.begin(), i->second.end());
00203 res.push_back(make_pair(i->second[i->second.size()/2], i->first));
00204 }
00205
00206
00207
00208 sort(res.begin(), res.end());
00209 for(unsigned int i=0; i < res.size(); i++)
00210 cout << res[i].second << " " << setprecision(5) << setw(10) << res[i].first << " ";
00211 cout << endl;
00212 ColIter<Size, C+1, (Cols> Size*1000)>::iter();
00213 }
00214 };
00215
00216 template<int Size, int C> struct ColIter<Size, C, 1>
00217 {
00218
00219 static void iter()
00220 {
00221 }
00222 };
00223
00224 #ifndef SIZE
00225 #define SIZE 2
00226 #endif
00227
00228 int main()
00229 {
00230 ColIter<SIZE>::iter();
00231
00232 return global_sum != 123456789.0;
00233 }