00001 /****************************************************************************** 00002 * SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3 * 00003 * (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS * 00004 * * 00005 * This library is free software; you can redistribute it and/or modify it * 00006 * under the terms of the GNU Lesser General Public License as published by * 00007 * the Free Software Foundation; either version 2.1 of the License, or (at * 00008 * your option) any later version. * 00009 * * 00010 * This library is distributed in the hope that it will be useful, but WITHOUT * 00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * 00013 * for more details. * 00014 * * 00015 * You should have received a copy of the GNU Lesser General Public License * 00016 * along with this library; if not, write to the Free Software Foundation, * 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 00018 ******************************************************************************* 00019 * SOFA :: Framework * 00020 * * 00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,* 00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza, * 00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy * 00024 * * 00025 * Contact information: contact@sofa-framework.org * 00026 ******************************************************************************/ 00027 #ifndef SOFA_HELPER_LCPSOLVER_INL 00028 #define SOFA_HELPER_LCPSOLVER_INL 00029 00030 #include <sofa/helper/LCPSolver.h> 00031 00032 namespace sofa 00033 { 00034 00035 namespace helper 00036 { 00037 00038 #define EPS 0.00001 // epsilon pour tests = 0 00039 #define EPSP 0.00000000001 // epsilon pour pivot 00040 #define MAX_BOU 50 // nombre maximal de boucles de calcul 00041 00042 // ----------------------------------------------------------------- 00043 // --- Resoud un LCP �rit sous la forme U = q + M.F 00044 // --- dim : dimension du pb 00045 // --- res[0..dim-1] = U 00046 // --- res[dim..2*dim-1] = F 00047 // ----------------------------------------------------------------- 00048 template <int dim> bool LCPSolver<dim>::solve(const double *q, const Matrix &M, double *res) 00049 { 00050 int ii, jj; 00051 int ligPiv; // ligne du pivot 00052 int colPiv; // colonne du pivot 00053 double pivot; // pivot 00054 double min; // recherche du minimum pour le pivot 00055 double coeff; // valeur du coefficient de la combinaison lin�ire 00056 int boucles; // ii du nombre de passages dans la boucle 00057 double mat[dim][2*dim+1]; 00058 int base[dim]; // base des variables non nulles 00059 00060 // matrix initialization 00061 for (ii=0; ii<dim; ii++) { 00062 // colonnes correspondantes ?w 00063 for(jj=0;jj<dim;jj++) { 00064 if(jj==ii) { 00065 mat[ii][jj] = 1; 00066 } 00067 else { 00068 mat[ii][jj] = 0; 00069 } 00070 } 00071 // colonnes correspondantes ?z 00072 for (;jj<2*dim;jj++) { 00073 mat[ii][jj] = -(M[ii][jj-dim]); 00074 } 00075 // colonne correspondante ?q 00076 mat[ii][jj] = q[ii]; 00077 } 00078 00079 // initialisation de la base 00080 for(ii=0;ii<dim;ii++) { 00081 base[ii]=ii; 00082 } 00083 00084 // initialisation du nombre de boucles 00085 boucles=0; 00086 00087 // recherche de la ligne du pivot 00088 ligPiv=-1; 00089 min = -EPS; 00090 for(ii=0;ii<dim;ii++) { 00091 if (mat[ii][2*dim]<min) { 00092 ligPiv=ii; 00093 min=mat[ii][2*dim]; 00094 } 00095 } 00096 00097 // tant que tous les q[i] ne sont pas > 0 et qu'on ne boucle pas trop 00098 while ((ligPiv>=0) && (boucles<MAX_BOU)) { 00099 // augmentation du nombre de passages dans cette boucle 00100 boucles++; 00101 // recherche de la colonne du pivot 00102 if (base[ligPiv]<dim) { 00103 // c'est un wi dans la base 00104 colPiv=dim+base[ligPiv]; 00105 } 00106 else { 00107 // c'est un zi dans la base 00108 colPiv=base[ligPiv]-dim; 00109 } 00110 00111 // stockage de la valeur du pivot 00112 pivot=mat[ligPiv][colPiv]; 00113 00114 // si le pivot est nul, le LCP echoue 00115 if (fabs(pivot)<EPSP) { 00116 // printInfo(q,M,base, mat, dim); 00117 printf(" + No solution to LCP + \n"); 00118 boucles=MAX_BOU; 00119 return false; 00120 } else { 00121 // division de la ligne du pivot par le pivot 00122 for(ii=0;ii<2*dim+1;ii++) { 00123 mat[ligPiv][ii]/=pivot; 00124 } 00125 00126 // combinaisons lin�ires mettant la colonne du pivot a 0 00127 for(ii=0;ii<dim;ii++) { 00128 if (ii!=ligPiv) { 00129 coeff=mat[ii][colPiv]; 00130 for(jj=0;jj<2*dim+1;jj++) { 00131 mat[ii][jj]-=coeff*mat[ligPiv][jj]; 00132 } 00133 } 00134 } 00135 00136 // on rentre dans la base la nouvelle variable 00137 base[ligPiv]=colPiv; 00138 00139 // recherche de la nouvelle ligne du pivot 00140 ligPiv=-1; 00141 min = -EPS; 00142 for(ii=0;ii<dim;ii++) { 00143 if (mat[ii][2*dim]<min) { 00144 ligPiv=ii; 00145 min=mat[ii][2*dim]; 00146 } 00147 } 00148 00149 } 00150 } 00151 00152 // stockage du resultat 00153 for(ii=0;ii<2*dim;ii++) { 00154 res[ii]=0; 00155 } 00156 // si on est arrive a r�oudre le pb, seules les variables en base sont non nulles 00157 if (boucles<MAX_BOU) { 00158 for(ii=0;ii<dim;ii++) { 00159 res[base[ii]]=mat[ii][2*dim]; 00160 } 00161 } 00162 00163 return true; 00164 } 00165 00166 00167 // ----------------------------------------------------------------- 00168 // --- 00169 // ----------------------------------------------------------------- 00170 template <int dim> void LCPSolver<dim>::printInfo(double *q, Matrix &M) 00171 { 00172 int ii, jj; 00173 00174 // affichage de la matrice du LCP 00175 printf("M = ["); 00176 for(ii=0;ii<dim;ii++) { 00177 for(jj=0;jj<dim;jj++) { 00178 printf("\t%.4f",M[ii][jj]); 00179 } 00180 printf("\n"); 00181 } 00182 printf(" ]\n\n"); 00183 00184 // affichage de q 00185 printf("q = ["); 00186 for (ii=0;ii<dim;ii++) { 00187 printf("\t%.4f\n",q[ii]); 00188 } 00189 printf(" ]\n\n"); 00190 00191 // afficahge base courante 00192 /* printf("B = ["); 00193 for(ii=0;ii<dim;ii++) { 00194 printf("\t%d",base[ii]); 00195 } 00196 printf("\t]\n\n"); 00197 00198 // affichage matrice courante 00199 printf("mat = ["); 00200 for(ii=0;ii<dim;ii++) { 00201 for(jj=0;jj<2*dim+1;jj++) { 00202 printf("\t%.4f",mat[ii][jj]); 00203 } 00204 printf("\n"); 00205 } 00206 printf(" ]\n\n"); */ 00207 } 00208 00209 //template<> class LCPSolver<3>; 00210 //template<> class LCPSolver<5>; 00211 00212 } // namespace helper 00213 00214 } // namespace sofa 00215 00216 #endif
1.5.7.1