LCPSolver.inl

Go to the documentation of this file.
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

Generated on Sun Nov 23 02:29:30 2008 for Sofa by  doxygen 1.5.7.1