Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExamplePolynomialSolve.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 /** @example ExamplePolynomialSolve.cpp
27  @relates PolynomialSolve
28  @ingroup g_examples
29  @brief example for PolynomialSolve usage
30  @author MIP
31 */
32 
33 
34 #include <Base/Common/BIASpragma.hh>
35 
36 #include <MathAlgo/PolynomialSolve.hh>
37 #include <Base/Math/Random.hh>
38 #include <algorithm>
39 
40 using namespace BIAS;
41 using namespace std;
42 
43 bool debug=false;
44 double maxerr=1e-8;
45 
46 namespace std{
47  bool operator<(complex<double>& left, complex<double>& right)
48  {
49  return (left.real()<right.real());
50  }
51  bool operator<(const complex<double>& left, const complex<double>& right)
52  {
53  return (left.real()<right.real());
54  }
55 }
56 
57 void solout(vector<POLYNOMIALSOLVE_TYPE>& sol)
58 {
59  sort(sol.begin(), sol.end());
60  int s=(int)sol.size();
61  cout.precision(20);
62  for (int i=0; i<s; i++)
63  if (debug) cout << sol[i] << " ";
64  if (debug) cout << endl;
65 }
66 
67 void solout(vector<complex<POLYNOMIALSOLVE_TYPE> >& sol)
68 {
69  sort(sol.begin(), sol.end());
70  int s=(int)sol.size();
71  cout.precision(20);
72  for (int i=0; i<s; i++)
73  if (debug) cout << sol[i] << " ";
74  if (debug) cout << endl;
75 }
76 
77 
78 void errout(vector<POLYNOMIALSOLVE_TYPE>& sol,
79  vector<POLYNOMIALSOLVE_TYPE>& gtsol)
80 {
81  sort(sol.begin(), sol.end());
82  int s=(int)sol.size();
83  cout.precision(20);
84  if (debug) cout << "error: ";
85  for (int i=0; i<s; i++){
86 
87  if (debug) cout << fabs(sol[i]-gtsol[i]) << " ";
88  if (fabs(sol[i]-gtsol[i])>maxerr) {
89  cerr << "\n\n\nerror bigger than "<<maxerr<<"\n" <<endl;
90  debug=true;
91  cout << "ground truth: ";
92  solout(gtsol);
93  cout << "computed: ";
94  solout(sol);
95  cout << "error: ";
96  for (int i=0; i<s; i++) cout << fabs(sol[i]-gtsol[i]) << " ";
97  cout << endl;
98  cerr << "\n\n\nthis happens if the roots of the polynomial are close together\n\n\n"
99  <<endl;
100  BIASASSERT(false);
101  }
102  }
103  if (debug) cout << endl << endl;
104 }
105 
106 void errout(vector<complex<POLYNOMIALSOLVE_TYPE> >& sol,
107  vector<POLYNOMIALSOLVE_TYPE>& gtsol)
108 {
109  sort(sol.begin(), sol.end());
110  int s=(int)sol.size();
111  cout.precision(20);
112  if (debug) cout << "error: ";
113  for (int i=0; i<s; i++){
114  if (debug) cout << fabs((sol[i]).real()-gtsol[i]) << " ";
115  if (fabs((sol[i]).real()-gtsol[i])>maxerr) {
116  cerr << "\n\n\nerror bigger than "<<maxerr<<"\n" <<endl;
117  debug=true;
118  cout << "ground truth: ";
119  solout(gtsol);
120  cout << "computed: ";
121  solout(sol);
122  cout << "error: ";
123  for (int i=0; i<s; i++) cout << fabs((sol[i]).real()-gtsol[i]) << " ";
124  cout << endl;
125  cerr << "\n\n\nthis happens if the roots of the polynomial are close together\n\n\n"
126  <<endl;
127  BIASASSERT(false);
128  }
129  }
130  if (debug) cout << endl << endl;
131 }
132 
133 /** @author woelk 08/2004 */
134 //int main(int argc, char *argv[])
135 int main()
136 {
137  PolynomialSolve ps;
138 
139  //vector<double> coeff(5);
140 // // coeff[0]=-3.26315441046362053612028830685;
141 // // coeff[1]=13.0504510585815651779739710037;
142 // // coeff[2]=-19.574778123864497558770381147;
143 // // coeff[3]=13.0508215983482731559206513339;
144 // // coeff[4]=-3.26334012093903513829218354658;
145 //
146 // coeff[0]=-5.3812376413659608331840900064;
147 // coeff[1]=21.5206398747126961268349987222;
148 // coeff[2]=-32.2795617934279306382450158708;
149 // coeff[3]=21.5221584472618552297262795037;
150 // coeff[4]=-5.38199880981732103890635698917;
151 //
152 // vector<double> roots;
153 // ps.Quartic(coeff, roots);
154 // //ps.Numeric(coeff, roots);
155 //
156 // /*
157 // octave:2> x=roots(coeff)
158 // x =
159 //
160 // 0.99948 + 0.02686i
161 // 0.99948 - 0.02686i
162 // 1.00105 + 0.00000i
163 // 0.99933 + 0.00000i
164 //
165 // coefs2:
166 // 0.999231378314545 + 0.030940956057273i
167 // 0.999231378314545 - 0.030940956057273i
168 // 1.004259532432780 + 0.000000000000000i
169 // 0.996476651583676 + 0.000000000000000i
170 //
171 // */
172 //
173 // if(roots.size()==0)
174 // {
175 // cout<<"PolynomialSolve found no roots! although"<<endl;
176 // }
177 // else
178 // {
179 // for(unsigned int r=0; r<roots.size(); r++)
180 // {
181 // cout<<r<<": "<<roots[r]<<endl;
182 // }
183 // }
184 
185  Random ran;
186 
187  int num=9000;
188  //num=1; debug=true; ps.AddDebugLevel(D_PS_COEFF);
189  int maxdeg=8;
190  double maxsol=5e1;
191 
192  int deg, nums;
193  vector<POLYNOMIALSOLVE_TYPE> coeff, sol, gtsol;
194  vector<complex<POLYNOMIALSOLVE_TYPE> > csol;
195 
196  for (int n=0; n<num; n++){
197  deg=ran.GetUniformDistributedInt(0, maxdeg);
198  // deg=5;
199  if (debug){
200  cout << "-----------------"<< setw(3) << n <<"------------------"<<endl;
201  cout << "using a polynom of degree "<<deg<<endl;
202  } else {
203  if (n%10==0){
204  cout << n << flush;
205  } else {
206  cout << "." << flush;
207  }
208  }
209 
210  gtsol.resize(deg);
211 
212  // first generate random solutions
213  for (int d=0; d<deg; d++){
214  gtsol[d]=ran.GetUniformDistributed(-maxsol, maxsol);
215  //gtsol[d]=d+1;
216  if (debug)
217  cout << d << "th root: "<<gtsol[d]<<endl;
218  }
219  sort(gtsol.begin(), gtsol.end());
220 
221  // now calculate the coefficients
222  ps.CalCoefficients(gtsol, coeff);
223  if (debug){
224  for (int i=0; i<deg+1; i++){
225  cout << i << "th coefficient: "<< coeff[i]<<endl;
226  }
227  }
228  /* // test for CheckCoefficients
229  coeff[deg]=0.0; if (deg>1) coeff[deg-1]=1e-12;
230  ps.CheckCoefficients(coeff, 1e-11);
231  if (debug){
232  for (int i=0; i<coeff.size(); i++){
233  cout << i << "th coefficient: "<< coeff[i]<<endl;
234  }
235  }
236  */
237 
238  // check if coefficients are correct
239  if (debug) {
240  cout << "polynomial at ground truth roots: "<<endl;
241  for (int i=0; i<deg; i++){
242  cout << "p("<<-gtsol[i]<<") = "<<ps.EvaluatePolynomial(gtsol[i], coeff)
243  << " ";
244  cout << endl;
245  }
246  }
247 
248  nums=ps.Solve(coeff, sol);
249  if (debug) cout <<"Solve (real) found "<<nums<<" solutions:\n";
250  if (nums>0) { solout(sol); errout(sol, gtsol); }
251  nums=ps.Solve(coeff, csol);
252  if (debug) cout <<"Solve (complex) found "<<nums<<" solutions:\n";
253  if (nums>0) { solout(csol); errout(csol, gtsol); }
254 
255  nums=ps.Numeric(coeff, sol);
256  if (debug)cout<<"Numeric (real) found "<<nums<<" solutions:\n";
257  if (nums>0) { solout(sol); errout(sol, gtsol); }
258  nums=ps.Numeric(coeff,csol);
259  if (debug) cout<<"Numeric (complex) found "<<nums<<" solutions:\n";
260  if (nums>0) { solout(csol); errout(csol, gtsol); }
261 
262  if (deg<=4){
263  nums=ps.Analytic(coeff, sol);
264  if (debug) cout << "Analytic (real) found "<<nums<<" solutions:\n";
265  if (nums>0) { solout(sol); errout(sol, gtsol); }
266  }
267  if (deg<=3){
268  nums=ps.Analytic(coeff, csol);
269  if (debug) cout << "Analytic (complex) found "<<nums<<" solutions:\n";
270  if (nums>0) { solout(csol); errout(csol, gtsol); }
271  }
272 
273  }
274 
275  return 0;
276 }
int Numeric(const std::vector< POLYNOMIALSOLVE_TYPE > &coeff, std::vector< POLYNOMIALSOLVE_TYPE > &sol)
solves polynomial of arbitrary order n numerically coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0 c...
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
base class for solving polynomial equations
int GetUniformDistributedInt(const int min, const int max)
get uniform distributed random variable including min/max
Definition: Random.cpp:139
POLYNOMIALSOLVE_TYPE EvaluatePolynomial(const POLYNOMIALSOLVE_TYPE x, const std::vector< POLYNOMIALSOLVE_TYPE > &coeff) const
numerically robust way to evaluate a polynomial at position x, uses Horner scheme (same principle as ...
void CalCoefficients(const std::vector< POLYNOMIALSOLVE_TYPE > &sol, std::vector< POLYNOMIALSOLVE_TYPE > &coeff)
inverse function, calculates coefficients from the solutions
int Analytic(const std::vector< POLYNOMIALSOLVE_TYPE > &coeff, std::vector< POLYNOMIALSOLVE_TYPE > &sol)
solves polynomial of arbitrary order n&lt;=4 analytically coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]...
int Solve(const std::vector< POLYNOMIALSOLVE_TYPE > &coeff, std::vector< POLYNOMIALSOLVE_TYPE > &sol)
solve polynomial of arbitrary order n coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0 coeff[n]!=0...
class for producing random numbers from different distributions
Definition: Random.hh:51