Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
testMatrixConditionNumber.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Test matrix condition number.
32 */
33
38
39#include <iostream>
40#include <stdlib.h>
41#include <visp3/core/vpMatrix.h>
42
43#ifdef ENABLE_VISP_NAMESPACE
44using namespace VISP_NAMESPACE_NAME;
45#endif
46int test_condition_number(const std::string &test_name, const vpMatrix &M);
47
48int test_condition_number(const std::string &test_name, const vpMatrix &M)
49{
50 double precision = 1e-6;
51
52 bool is_square = (M.getCols() == M.getRows() ? true : false);
53 double inducedL2_norm_inv = 0, cond_inv = 0;
54
55 double inducedL2_norm = M.inducedL2Norm();
56 double inducedL2_norm_pinv = M.pseudoInverse().inducedL2Norm();
57 double cond = M.cond();
58 double cond_pinv = inducedL2_norm * inducedL2_norm_pinv;
59
60 vpMatrix kerMt;
61 double rank = M.kernel(kerMt);
62
63 if (is_square) {
64 inducedL2_norm_inv = M.inverseByLU().inducedL2Norm();
65 cond_inv = inducedL2_norm * inducedL2_norm_inv;
66 }
67
68 M.print(std::cout, 4, test_name);
69 std::cout << " Matrix rank: " << rank << std::endl;
70 std::cout << " Matrix induced L2 norm ||M||_L2: " << inducedL2_norm << std::endl;
71 if (is_square) {
72 std::cout << " Inverse induced L2 norm ||M^-1||_L2: " << inducedL2_norm_inv << std::endl;
73 }
74 std::cout << " Pseudo inverse induced L2 norm norm ||M^+||_L2: " << inducedL2_norm_pinv << std::endl;
75 if (is_square) {
76 std::cout << " Condition number such as cond(M)=||M||_L2 * ||M^-1||_L2: " << cond_inv << std::endl;
77 }
78 std::cout << " Condition number such as cond(M)=||M||_L2 * ||M^+||_L2: " << cond_pinv << std::endl;
79 std::cout << " Condition number cond(M): " << cond << std::endl;
80 if (!vpMath::equal(cond, cond_pinv, precision)) {
81 std::cout << " Condition number differ from the one computed with the pseudo inverse" << std::endl;
82 return EXIT_FAILURE;
83 }
84 if (is_square) {
85 if (!vpMath::equal(cond, cond_inv, precision)) {
86 std::cout << " Condition number differ from the one computed with the inverse" << std::endl;
87 return EXIT_FAILURE;
88 }
89 }
90
91 return EXIT_SUCCESS;
92}
93
94int main()
95{
96#if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV)
97 vpMatrix M(3, 3);
98 M.eye();
99
100 if (test_condition_number("* Test square matrix M", M)) {
101 std::cout << " - Condition number computation fails" << std::endl;
102 return EXIT_FAILURE;
103 }
104 else {
105 std::cout << " + Condition number computation succeed" << std::endl;
106 }
107
108 M.resize(2, 3);
109 M[0][0] = 1;
110 M[0][1] = 2;
111 M[0][2] = 3;
112 M[1][0] = 4;
113 M[1][1] = 5;
114 M[1][2] = 6;
115
116 if (test_condition_number("* Test rect matrix M", M)) {
117 std::cout << " - Condition number computation fails" << std::endl;
118 return EXIT_FAILURE;
119 }
120 else {
121 std::cout << " + Condition number computation succeed" << std::endl;
122 }
123
124 M = M.transpose();
125
126 if (test_condition_number("* Test rect matrix M", M)) {
127 std::cout << " - Condition number computation fails" << std::endl;
128 return EXIT_FAILURE;
129 }
130 else {
131 std::cout << " + Condition number computation succeed" << std::endl;
132 }
133
134 M.resize(3, 4);
135 M[0][0] = 1;
136 M[0][1] = 2;
137 M[0][2] = 3;
138 M[0][3] = 0;
139 M[1][0] = 4;
140 M[1][1] = 5;
141 M[1][2] = 6;
142 M[1][3] = 0;
143 M[2][0] = 0;
144 M[2][1] = 0;
145 M[2][2] = 0;
146 M[2][3] = 0;
147
148 if (test_condition_number("* Test rect matrix M", M)) {
149 std::cout << " - Condition number computation fails" << std::endl;
150 return EXIT_FAILURE;
151 }
152 else {
153 std::cout << " + Condition number computation succeed" << std::endl;
154 }
155
156 M = M.transpose();
157
158 if (test_condition_number("* Test rect matrix M", M)) {
159 std::cout << " - Condition number computation fails" << std::endl;
160 return EXIT_FAILURE;
161 }
162 else {
163 std::cout << " + Condition number computation succeed" << std::endl;
164 }
165 std::cout << "Test succeed" << std::endl;
166#else
167 std::cout << "Test ignored: install Lapack, Eigen3 or OpenCV" << std::endl;
168#endif
169 return EXIT_SUCCESS;
170}
unsigned int getCols() const
Definition vpArray2D.h:423
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
unsigned int getRows() const
Definition vpArray2D.h:433
static bool equal(double x, double y, double threshold=0.001)
Definition vpMath.h:470
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
double cond(double svThreshold=1e-6) const
int print(std::ostream &s, unsigned int length, const std::string &intro="") const
Definition vpMatrix.cpp:836
unsigned int kernel(vpMatrix &kerAt, double svThreshold=1e-6) const
vpMatrix inverseByLU() const
double inducedL2Norm() const
vpMatrix pseudoInverse(double svThreshold=1e-6) const
vpMatrix transpose() const