libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNEquationSolver.cpp
Go to the documentation of this file.
1 /* Copyright 2008-2016 INSA-Lyon, ENS-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNEquationSolver.cpp
19  *
20  * \author Jean DUONG, Yann LEYDIER
21  */
22 
25 #include <CRNException.h>
26 #include <CRNStringUTF8.h>
27 #include <CRNi18n.h> // Always last of includes !!!
28 
29 using namespace crn;
30 
42 MatrixDouble LinearSystem::Cramer(const SquareMatrixDouble &Coefficients, const MatrixDouble &ConstantTerms)
43 {
44  size_t n = Coefficients.GetRows();
45 
46  if ((ConstantTerms.GetRows() != n) || (ConstantTerms.GetCols() != 1))
47  {
48  throw ExceptionDimension(StringUTF8("LinearEquationsSystem::CramerSolver("
49  "const SquareMatrixDouble *Coefficients, const MatrixDouble *ConstantTerms): ") +
50  _("invalid or incompatible matrix dimensions"));
51  }
52  else
53  {
54  double D = Coefficients.Determinant();
55 
56  if (D == 0.0)
57  {
58  throw ExceptionRuntime(_("Equation has either no solution or an infinity of solutions."));
59  }
60 
61  MatrixDouble Solutions(n, 1, 0.0);
62 
63  for (size_t k = 0; k < n; k++)
64  {
65  SquareMatrixDouble Mk(Coefficients);
66 
67  for (size_t r = 0; r < n; r++)
68  {
69  Mk.At(r, k) = ConstantTerms.At(r, 0);
70  }
71 
72  double Dk = Mk.Determinant();
73 
74  Solutions.At(k, 0) = Dk / D;
75  }
76 
77  return Solutions;
78  }
79 }
80 
92 MatrixDouble LinearSystem::GaussJordan(const SquareMatrixDouble &Coefficients, const MatrixDouble &ConstantTerms)
93 {
94  size_t n = Coefficients.GetRows();
95 
96  if (ConstantTerms.GetRows() != n)
97  {
98  throw ExceptionDimension(StringUTF8("LinearEquationsSystem::GaussJordanSolver("
99  "const SquareMatrixDouble *Coefficients, const MatrixDouble *ConstantTerms): ") +
100  _("invalid or incompatible matrix dimensions"));
101  }
102  else
103  {
104  USquareMatrixDouble CopyCoefficients = CloneAs<SquareMatrixDouble>(Coefficients);
105  UMatrixDouble CopyConstantTerms = CloneAs<MatrixDouble>(ConstantTerms);
106 
107  for (size_t c = 0; c < n - 1; c++)
108  {
109  // Search the greatest pivot in column
110 
111  double Pivot = CopyCoefficients->At(c, c);
112  double AbsMaxPivot = fabs(Pivot);
113  size_t RowIndex = c;
114 
115  for (size_t r = c + 1 ; r < n; r++)
116  {
117  double Candidate = CopyCoefficients->At(r, c);
118 
119  if (fabs(Candidate) > AbsMaxPivot)
120  {
121  Pivot = Candidate;
122  AbsMaxPivot = fabs(Pivot);
123  RowIndex = r;
124  }
125  }
126 
127  // If no non-null pivot found, system may have infinite number of solutions
128 
129  if (Pivot == 0.0)
130  {
131  throw ExceptionRuntime(_("Equation has either no solution or an infinity of solutions."));
132  }
133 
134  if (RowIndex != c)
135  {
136  CopyCoefficients->SwapRows(c, RowIndex);
137  CopyConstantTerms->SwapRows(c, RowIndex);
138  }
139  // Elimination
140 
141  for (size_t r = c + 1; r < n; r++)
142  {
143  double Coeff = CopyCoefficients->At(r, c);
144 
145  if (Coeff != 0.0)
146  {
147  double Scale = - Coeff / Pivot;
148 
149  for (size_t k = c; k < n; k++)
150  {
151  CopyCoefficients->IncreaseElement(r, k, CopyCoefficients->At(c, k) * Scale);
152  }
153 
154  CopyConstantTerms->IncreaseElement(r, 0, CopyConstantTerms->At(c, 0) * Scale);
155  }
156  }
157  }
158  // End of loop for column
159 
160  MatrixDouble Solutions(n, 1, 0.0);
161 
162  Solutions.At(n - 1, 0) = CopyConstantTerms->At(n - 1, 0) / CopyCoefficients->At(n - 1, n - 1);
163 
164  for (auto r = int(n) - 2; r >= 0; --r)
165  {
166  double Cumul = 0.0;
167 
168  for (auto c = int(n) - 1; c > r; --c)
169  {
170  Cumul += CopyCoefficients->At(r, c) * Solutions.At(c, 0);
171  }
172 
173  Solutions.At(r, 0) = (CopyConstantTerms->At(r, 0) - Cumul) / CopyCoefficients->At(r, r);
174  }
175 
176  return Solutions;
177  }
178 }
179 
180 /*****************************************************************************/
189 double QuadraticEquation::Discriminant(double a, double b, double c) noexcept
190 {
191  return (b * b - 4.0 * a * c);
192 }
193 
194 /*****************************************************************************/
203 std::set<double> QuadraticEquation::RealRoots(double a, double b, double c) noexcept
204 {
205  double Delta = Discriminant(a, b, c);
206 
207  std::set<double> roots;
208 
209  if (a == 0.0)
210  {
211  roots.insert( - c / b);
212  }
213  else
214  {
215  double Inv2a = 1.0 / (2.0 * a);
216 
217  if (Delta == 0.0)
218  {
219  roots.insert(- b * Inv2a);
220  }
221  else
222  {
223  if (Delta > 0.0)
224  {
225  double SqrtDelta = sqrt(Delta);
226 
227  roots.insert((- b - SqrtDelta) * Inv2a);
228  roots.insert((- b + SqrtDelta) * Inv2a);
229  }
230  }
231  }
232 
233  return roots;
234 }
size_t GetRows() const noexcept
Returns the number of rows.
Definition: CRNMatrix.h:157
double Discriminant(double a, double b, double c) noexcept
Discriminant of trinom .
size_t GetCols() const noexcept
Returns the number of columns.
Definition: CRNMatrix.h:163
A generic runtime error.
Definition: CRNException.h:131
#define _(String)
Definition: CRNi18n.h:51
MatrixDouble GaussJordan(const SquareMatrixDouble &Coefficients, const MatrixDouble &ConstantTerms)
Resolution of linear equation system by the pivot method.
void Scale(ITER it_begin, ITER it_end, const double s)
Scale a collection of numbers.
Definition: CRNMath.h:103
std::set< double > RealRoots(double a, double b, double c) noexcept
Real roots of trinom .
A dimension error.
Definition: CRNException.h:119
double matrix class
const T & At(size_t pos) const noexcept
Definition: CRNMatrix.h:165
MatrixDouble Cramer(const SquareMatrixDouble &Coefficients, const MatrixDouble &ConstantTerms)
Resolution of linear equation system by the determinant method.
Square double matrix class.
A character string class.
Definition: CRNStringUTF8.h:49
double Determinant() const
Determinant.