Institut de Robòtica i Informàtica Industrial
KRD Group

The CuikSuite Project

cuiksystem.c

Go to the documentation of this file.
00001 #include "cuiksystem.h"
00002 
00003 #include "error.h"
00004 #include "boolean.h"
00005 #include "defines.h"
00006 #include "box_list.h"
00007 #include "box_heap.h"
00008 #include "simplex.h"
00009 #include "random.h"
00010 #include "filename.h"
00011 #include "geom.h"
00012 
00013 #include <stdlib.h>
00014 #include <gsl/gsl_linalg.h>
00015 
00016 #include <math.h>
00017 #include <string.h>
00018 #include <sys/time.h>
00019 #include <signal.h>
00020 #if (_USE_MPI)
00021   #include <mpi.h>
00022   #include <sys/resource.h>
00023   #include <time.h>
00024   #include <unistd.h>
00025 #endif
00026 
00027 
00028 
00038 /* Internal functions */
00039 
00056 void DummifyAndAddEquation(Tparameters *p,Tequation *eq,TCuikSystem *cs);
00057 
00069 void DummifyCuikSystem(Tparameters *p,TCuikSystem *cs);
00070 
00071 
00089 double EvaluateEqMin(void *b,void *cs);
00090 
00110 unsigned int ReduceBoxEquationWise(Tparameters *p,Tbox *b,TCuikSystem *cs);
00111 
00140 unsigned int ReduceBox(Tparameters *p,unsigned int varMask,Tbox *b,TCuikSystem *cs);
00141 
00163 void PostProcessBox(Tparameters *p,unsigned int c,
00164                     FILE *f_out,
00165                     Tlist *sol,
00166                     Theap *boxes,
00167                     Tbox *b,
00168                     TCuikSystem *cs);
00169 
00181 void CSRemoveUnusedVars(Tparameters *p,TCuikSystem *cs);
00182 
00183 
00213 boolean CSRemoveVarsWithCtRange(Tparameters *p,
00214                                 boolean *replaced,TLinearConstraint *lc,
00215                                 Tbox *borig,TCuikSystem *cs);
00216 
00260 boolean CSRemoveLCVars(Tparameters *p,unsigned int level,boolean *changed,
00261                        boolean *replaced,TLinearConstraint *lc,
00262                        Tbox *borig,TCuikSystem *cs);
00287 boolean SimplifyCuikSystem(Tparameters *p,TCuikSystem *cs);
00288 
00306 void ComputeSimpCuikSystemJacobian(TCuikSystem *cs);
00307 
00317 void DeleteSimpCuikSystemJacobian(TCuikSystem *cs);
00318 
00335 boolean UpdateCuikSystem(Tparameters *p,TCuikSystem *cs);
00336 
00350 void UnUpdateCuikSystem(TCuikSystem *cs);
00351 
00371 unsigned int ComputeSplitDimInt(Tparameters *p,Tbox *b,TCuikSystem *cs);
00372 
00392 void SaveCSState(char *fname,Tlist *lb,TCuikSystem *cs);
00393 
00407 void LoadCSState(char *fname,Tlist *lb,TCuikSystem *cs);
00408 
00409 
00410 /************************************************************************/
00411 /************************************************************************/
00412 /************************************************************************/
00413 
00414 /*
00415   The equation is dummified and the resulting equations and new variables
00416   are added to the cuik system.
00417 
00418   Dummification is performed in the last step of the simplification and, thus,
00419   this function operates in the sets of simplified equations and variables
00420 
00421   Dummification consists in changing all monomials of type x^2 or x*y by new
00422   variables 'z' and adding the corresponding equations (z=x^2 or z=x*y) to
00423   the system.
00424 
00425   The level of dummification is controlled by the 'dummify' parameter.
00426 
00427   This internal function is hidden to the user. In this way dummification is
00428   applied only after the system simplification.
00429   See AddEquation2CS and SimplifyCuikSystem.
00430 */
00431 void DummifyAndAddEquation(Tparameters *p,Tequation *eq,TCuikSystem *cs)
00432 {
00433   if (eq!=NULL)
00434     {
00435       unsigned int nf;
00436       unsigned int i,nv,mv;
00437       Tvariable_set *vars;
00438       unsigned int dummify;
00439       double epsilon;
00440       unsigned int eqType;
00441 
00442       dummify=(unsigned int)(GetParameter(CT_DUMMIFY,p));
00443       epsilon=GetParameter(CT_EPSILON,p);
00444 
00445       vars=GetEquationVariables(eq);
00446       eqType=GetEquationType(eq);
00447 
00448       nv=VariableSetSize(vars);
00449       mv=NVariables(&(cs->variables));
00450       for(i=0;i<nv;i++)
00451         {
00452           if (GetVariableN(i,vars)>=mv)
00453             Error("Unknown variable in AddEquation2CS");
00454         }
00455 
00456       nf=GetNumMonomials(eq);
00457       if (nf>0)
00458         {
00459           boolean keep; /* True if the equation is kept in its original form */
00460           
00461           /* Dummy equations are not dummified again */
00462           /*dummify equations with just one monomial introduce a
00463             too simple variable x=ct that is not simplified since
00464             the dummifications is performed after the simplification. */
00465           if ((eqType==DUMMY_EQ)||(GetNumMonomials(eq)==1))
00466             keep=TRUE; 
00467           else
00468             {
00469               switch (dummify)
00470                 {
00471                 case 0:
00472                   keep=TRUE;
00473                   break;
00474                 case 1:
00475                   keep=((LinearEquation(eq))||
00476                         (ParabolaEquation(eq))|| 
00477                         (SaddleEquation(eq))|| 
00478                         (CircleEquation(eq))|| 
00479                         (SphereEquation(eq)));
00480                   break;
00481                 case 2:
00482                   keep=((LinearEquation(eq))||
00483                         (ParabolaEquation(eq))|| 
00484                         (SaddleEquation(eq)));
00485                   break;
00486                 case 3:
00487                   keep=((LinearEquation(eq))||
00488                         (ParabolaEquation(eq))|| 
00489                         (SaddleEquation(eq))|| 
00490                         (CircleEquation(eq))|| 
00491                         (SphereEquation(eq))||
00492                         (GetEquationCmp(eq)!=EQU)); /*Inequalities are kept in original form*/
00493             
00494                   break;
00495                 case 4:
00496                   keep=((LinearEquation(eq))||
00497                         (ParabolaEquation(eq))|| 
00498                         (SaddleEquation(eq))||
00499                         (GetEquationCmp(eq)!=EQU)); /*Inequalities are kept in original form*/
00500                   break;
00501                 default:
00502                   Error("Undefined value for DUMMIFY parameter");
00503                 }
00504             }
00505 
00506           if (keep)
00507             AddEquation(eq,&(cs->equations));
00508           else
00509             {
00510               unsigned int j,p,vid1,vid2,vid3;
00511               Tmonomial *f,fnew;
00512               Tequation eqnew; /* Bilinear and quadratic monomials produce new auxiliary equations */
00513               Tequation eqlineal; /* The original equation is transformed into a lineal equation */
00514               char *vname;
00515               Tinterval range;
00516               Tvariable v;
00517               char *n1,*n2;
00518 
00519               InitEquation(&eqlineal);
00520               
00521               for(j=0;j<nf;j++) /* For all monomials in the equation to be dummified */
00522                 {
00523 
00524                   f=GetMonomial(j,eq);
00525                   vars=GetMonomialVariables(f);
00526                   nv=VariableSetSize(vars);
00527 
00528                   switch(nv)
00529                     {
00530                     case 1: /*A single variable in the monomial*/
00531                       p=GetVariablePowerN(0,vars);
00532 
00533                       switch(p)
00534                         {
00535                         case 1: /*One variable with degree 1*/
00536                           /* A linear monomial: just add it to the linear equation*/
00537                       
00538                           AddMonomial(f,&eqlineal); /* A copy of monomial 'f' is stored in eqlineal*/
00539                           break;
00540 
00541                         case 2:/*One varialbe With degree 2*/                 
00542                           /* Add a linear monomial to eqlinear with a dummy variable
00543                              and add the corresponding parabola equation*/
00544 
00545                           vid1=GetVariableN(0,vars);
00546 
00547                           /* Generate a new variable dummy that will stand for  x^2 */
00548                           n1=GetVariableName(GetVariable(vid1,&(cs->variables)));
00549                           NEW(vname,strlen(n1)+20,char);
00550                           sprintf(vname,"dummy_%s_2",n1);
00551                                                     
00552                           vid2=GetVariableID(vname,&(cs->variables));
00553 
00554                           if (vid2==NO_UINT)
00555                             {
00556                               /* if the dummy variable is a new one, add the corresponding
00557                                  dummy equation to the system */
00558 
00559                               NewVariable(DUMMY_VAR,vname,&v);
00560                               IntervalPow(GetVariableInterval(GetVariable(vid1,&(cs->variables))),2,&range);
00561                               SetVariableInterval(&range,&v);
00562                               
00563                               vid2=AddVariable(&v,&(cs->variables));
00564                               DeleteVariable(&v);
00565                               
00566                               /* Generate a new equation x^2-dummy=0 */
00567                               InitEquation(&eqnew);
00568                               
00569                               InitMonomial(&fnew);
00570                               AddVariable2Monomial(vid1,2,&fnew);
00571                               AddCt2Monomial( 1.0,&fnew);
00572                               AddMonomial(&fnew,&eqnew);
00573                               DeleteMonomial(&fnew);
00574                               
00575                               InitMonomial(&fnew);
00576                               AddVariable2Monomial(vid2,1,&fnew);
00577                               AddCt2Monomial(-1.0,&fnew);
00578                               AddMonomial(&fnew,&eqnew);
00579                               DeleteMonomial(&fnew);
00580                               
00581                               SetEquationCmp(EQU,&eqnew);
00582                               SetEquationValue(0.0,&eqnew);
00583                               /*The derive equations is of the same type as the origiona one*/
00584                               SetEquationType(DUMMY_EQ,&eqnew);
00585                               
00586                               AddEquation(&eqnew,&(cs->equations));
00587                               DeleteEquation(&eqnew);
00588                             }
00589                           free(vname);
00590 
00591                           /*Now add the lineal monomial using the new dummy variable to eqlineal*/
00592                           InitMonomial(&fnew);
00593                           AddVariable2Monomial(vid2,1,&fnew);
00594                           AddCt2Monomial(GetMonomialCt(f),&fnew);
00595                           AddMonomial(&fnew,&eqlineal);
00596                           DeleteMonomial(&fnew);
00597                           break;
00598 
00599                         default:
00600                           Error("The input system to DummifyCuikSystem is not in canonical form");
00601                           break;
00602                         }
00603                       break;
00604 
00605                     case 2: /*Two variables in the monomial*/
00606                       if ((GetVariablePowerN(0,vars)==1)&&
00607                           (GetVariablePowerN(1,vars)==1)) /*The two of them with degree 1*/
00608                         {
00609                           /*Get the two variables involved in the product we have to rewrite*/
00610                           vid1=GetVariableN(0,vars);
00611                           vid2=GetVariableN(1,vars);
00612                           
00613                           /*Generate a new dummy variable*/
00614                           n1=GetVariableName(GetVariable(vid1,&(cs->variables)));
00615                           n2=GetVariableName(GetVariable(vid2,&(cs->variables)));
00616                           NEW(vname,strlen(n1)+strlen(n2)+20,char);
00617                           sprintf(vname,"dummy_%s_%s",n1,n2);
00618                                         
00619                           vid3=GetVariableID(vname,&(cs->variables));
00620                           if (vid3==NO_UINT)
00621                             {
00622 
00623                               NewVariable(DUMMY_VAR,vname,&v);
00624                               IntervalProduct(GetVariableInterval(GetVariable(vid1,&(cs->variables))),
00625                                               GetVariableInterval(GetVariable(vid2,&(cs->variables))),
00626                                               &range);
00627                               SetVariableInterval(&range,&v);
00628                               
00629                               vid3=AddVariable(&v,&(cs->variables));
00630                               DeleteVariable(&v);
00631 
00632                               /* Generate the dummy equation X*Y-dummy=0*/
00633                               InitEquation(&eqnew);
00634                               
00635                               InitMonomial(&fnew);
00636                               AddVariable2Monomial(vid1,1,&fnew);
00637                               AddVariable2Monomial(vid2,1,&fnew);
00638                               AddCt2Monomial( 1.0,&fnew);
00639                               AddMonomial(&fnew,&eqnew);
00640                               DeleteMonomial(&fnew);
00641                               
00642                               InitMonomial(&fnew);
00643                               AddVariable2Monomial(vid3,1,&fnew);
00644                               AddCt2Monomial(-1.0,&fnew);
00645                               AddMonomial(&fnew,&eqnew);
00646                               DeleteMonomial(&fnew);
00647                               
00648                               SetEquationCmp(EQU,&eqnew);
00649                               SetEquationValue(0.0,&eqnew);
00650                               /*The derive equations is of the same type as the origiona one*/
00651                               SetEquationType(DUMMY_EQ,&eqnew);
00652 
00653                               AddEquation(&eqnew,&(cs->equations));
00654                               DeleteEquation(&eqnew);
00655                             }
00656                           free(vname);
00657 
00658                           /*Now add the lineal monomial using the new dummy variable to eqlienal*/
00659                           InitMonomial(&fnew);
00660                           AddVariable2Monomial(vid3,1,&fnew);
00661                           AddCt2Monomial(GetMonomialCt(f),&fnew);
00662                           AddMonomial(&fnew,&eqlineal);
00663                           DeleteMonomial(&fnew);
00664                         }
00665                       else
00666                         /* One of the 2 variables in the monomial has degree >1 */
00667                         Error("The input system to DummifyCuikSystem is not in canonical form");
00668                       break;
00669 
00670                     default:
00671                       /* A monomial with more than 2 variables */
00672                       Error("The input system to DummifyCuikSystem is not in canonical form");
00673                     }
00674 
00675                 } /* Proceed with next monomial in the under-dummification equation*/
00676 
00677               /* The linearized original equation is added to the system */
00678 
00679               SetEquationCmp(GetEquationCmp(eq),&eqlineal);
00680               SetEquationValue(GetEquationValue(eq),&eqlineal);
00681               /*The resulting lineal equation is of the same type as the original equation*/
00682               SetEquationType(eqType,&eqlineal);
00683 
00684               AddEquation(&eqlineal,&(cs->equations));
00685               DeleteEquation(&eqlineal);
00686             }
00687         }
00688     }
00689 }
00690 
00691 void DummifyCuikSystem(Tparameters *p,TCuikSystem *cs)
00692 {
00693   unsigned int i,neq;
00694   Tequations eqs;
00695   unsigned int dummify;
00696   double epsilon;
00697   
00698   dummify=(unsigned int)(GetParameter(CT_DUMMIFY,p));
00699   epsilon=GetParameter(CT_EPSILON,p);
00700 
00701   CopyEquations(&eqs,&(cs->equations));
00702   DeleteEquations(&(cs->equations));
00703   InitEquations(&(cs->equations));
00704 
00705   neq=NEquations(&eqs);
00706   for(i=0;i<neq;i++)
00707     DummifyAndAddEquation(p,GetEquation(i,&eqs),cs);
00708 
00709   DeleteEquations(&eqs);
00710 }
00711 
00712 unsigned int ReduceBoxEquationWise(Tparameters *p,Tbox *b,TCuikSystem *cs)
00713 {
00714   boolean empty;
00715   boolean small;
00716   boolean significantReduction;
00717   Tbox b_orig;
00718   unsigned int i,j;
00719   double rho,smallSigma,epsilon;
00720   double mi_r;
00721   double reduction;
00722 
00723   rho=GetParameter(CT_RHO,p);
00724   epsilon=GetParameter(CT_EPSILON,p);
00725   smallSigma=GetParameter(CT_SMALL_SIGMA,p);
00726 
00727   /*default values*/
00728   empty=FALSE;
00729   significantReduction=FALSE;
00730   small=FALSE;
00731 
00732   #if (_DEBUG>2)
00733     printf("    Croping box: ");
00734     PrintBox(stdout,b);
00735     printf("      Size in: %g\n",GetBoxSize(cs->systemVar,b));
00736   #endif
00737 
00738   do {
00739     CopyBox(&b_orig,b);
00740 
00741     for(j=0;((!empty)&&(j<cs->nequations));j++)
00742       {
00743         #if (_DEBUG>5)
00744           printf("          Croping with equation %u: \n",j);
00745           printf("            Input box: "); 
00746           PrintBox(stdout,b);
00747           printf("            s: %g  v:%g\n",GetBoxSize(NULL,b),GetBoxVolume(NULL,b));
00748         #endif
00749         if (CropEquation(j,epsilon,rho,b,&(cs->equations))==EMPTY_BOX)
00750           empty=TRUE;
00751         #if (_DEBUG>5)
00752           if (empty)
00753             printf("            Empty output box\n");
00754           else
00755             {
00756               printf("            Output box: "); 
00757               PrintBox(stdout,b);
00758               printf("            s: %g  v:%g\n",GetBoxSize(NULL,b),GetBoxVolume(NULL,b));
00759             }
00760         #endif
00761       }
00762 
00763     if (!empty)
00764       {
00765         mi_r=1.0;
00766         for(i=0;i<cs->nvariables;i++)
00767           {
00768             /*variables of all types are affected by crop*/
00769             reduction=IntervalSize(GetBoxInterval(i,b))/IntervalSize(GetBoxInterval(i,&b_orig));
00770             if (reduction<mi_r) mi_r=reduction; 
00771           }
00772 
00773         significantReduction=(mi_r<rho);
00774         small=(GetBoxSize(cs->systemVar,b)<=smallSigma);
00775 
00776         #if (_DEBUG>2)
00777           printf("      Crop reduction: %f\n",mi_r);
00778           if (small)
00779             printf("        Tiny boxes are not reduced any more\n");
00780           else
00781             {
00782               if (significantReduction) 
00783                 printf("        Large reduction. Cropping again\n");
00784             }
00785         #endif
00786       }
00787     DeleteBox(&b_orig);
00788     
00789   } while ((!empty)&&(!small)&&(significantReduction));
00790   
00791   #if (_DEBUG>2)
00792     if (empty)
00793       printf("    Empty in Crop\n");
00794     else
00795       {
00796         printf("    Croped box: ");
00797         PrintBox(stdout,b);
00798         printf("      Size out: %g\n",GetBoxSize(cs->systemVar,b));
00799       }
00800   #endif
00801     
00802   if (empty)
00803     return(EMPTY_BOX);
00804   else
00805     return(REDUCED_BOX);
00806 }
00807 
00808 /*
00809   This is the basic function of the solver. This function includes the
00810   ShrinkBox procedure described in our papers plus a loop interating
00811   ShrinkBox as far as the box is significantly reduced (and still not empty).
00812 
00813   Thus, ReduceBox takes an input box 'b' and reduces it as much as possible by removing
00814   parts that do not include any solution point.
00815   It returns information about what happened in the box shrinking process
00816 
00817       ERROR_IN_PROCESS: When one of the simplex failed due to numerical inestabilities
00818                         The better the simplex implementation the less likely this
00819                         output.
00820 
00821       EMPTY_BOX: The box includes no solution. In this case the output box is
00822                  undefined (it includes empty intervals).
00823 
00824       REDUCED_BOX: The box was reduced and it has to be processed further to determine
00825                    if it includes any solution.
00826 
00827       REDUCED_BOX_WITH_SOLUTION: The box was been reduced and one of the reduction
00828                                  steps was contractive. This indicates the box
00829                                  includes a solution point.
00830  */
00831 unsigned int ReduceBox(Tparameters *p,unsigned int varMask,Tbox *b,TCuikSystem *cs)
00832 {
00833   /*The box can only be reduced if we have constraints*/
00834   if (cs->empty)
00835     return(REDUCED_BOX);
00836   else
00837     {
00838       boolean empty;
00839       boolean significantReduction;
00840       boolean small;
00841       boolean hasSolution;
00842       boolean err;
00843       boolean boxOK;
00844       unsigned int e;
00845       double mi_r,ma_s;
00846       double reduction,size;
00847       unsigned int i,j;
00848       Tbox b_orig;
00849       TSimplex lp;
00850       double epsilon,smallSigma,sigma,rho,lr2tm_q,lr2tm_s;
00851       unsigned int safe_simplex;
00852       boolean repeatLoop;
00853 
00854       if (!cs->updated)
00855         Error("Non-updated CS in ReduceBox");
00856 
00857       epsilon=GetParameter(CT_EPSILON,p);
00858       sigma=GetParameter(CT_SIGMA,p);
00859       smallSigma=GetParameter(CT_SMALL_SIGMA,p);
00860       rho=GetParameter(CT_RHO,p);
00861       lr2tm_q=GetParameter(CT_LR2TM_Q,p);
00862       lr2tm_s=GetParameter(CT_LR2TM_S,p);
00863       safe_simplex=(unsigned int)(GetParameter(CT_SAFE_SIMPLEX,p));
00864 
00865       /*default values*/
00866       empty=FALSE;
00867       hasSolution=FALSE;
00868       err=FALSE;                
00869       boxOK=TRUE;
00870       small=FALSE;
00871       significantReduction=FALSE;
00872       repeatLoop=FALSE;
00873 
00874       do { 
00875         #if (_DEBUG>2)
00876           printf("\n  Go for box reduction via crop+simplex\n");        
00877           printf("  InputBox: "); PrintBox(stdout,b);
00878           printf("    s: %g  v:%g\n",GetBoxSize(NULL,b),GetBoxVolume(NULL,b));
00879         #endif
00880 
00881         /*****************************************************************/
00882         /* One step of box reduction */
00883 
00884         /*#if ((!_USE_MPI)&&(_DEBUG==1))*/
00885         #if ((!_USE_MPI)&&(_DEBUG>1))
00886           fprintf(stderr,".");fflush(stderr);
00887         #endif
00888 
00889         NewBoxReduction(&(cs->st));
00890 
00891         /* First we do an equation wise reduction of the ranges -> Crop equation 
00892            repeated for each equation as far as we get a significant box reduction */
00893 
00894         empty=(ReduceBoxEquationWise(p,b,cs)==EMPTY_BOX);
00895 
00896         /* If the equation-wise reduction gives a full box, proceed with the global
00897            test based on linear programming */
00898 
00899         if (empty)
00900           repeatLoop=FALSE; /*There is no need to iterate*/
00901         else
00902           {
00903             SimplexCreate(epsilon,cs->nvariables,&lp);
00904 
00905             /* Add the linear constraints bounding the equations. This include
00906                croping the input ranges if necessary */
00907 
00908             for(j=0;((!empty)&&(j<cs->nequations));j++)
00909               {
00910                 if (!AddEquation2Simplex(j,
00911                                          lr2tm_q,lr2tm_s,
00912                                          epsilon,rho,
00913                                          b,&(cs->variables),
00914                                          &lp,&(cs->equations)))
00915                   empty=TRUE;
00916               }
00917 
00918             boxOK=TRUE;
00919             err=FALSE;
00920             small=FALSE;
00921             significantReduction=FALSE;
00922 
00923             /* Use the simplex to reduce the ranges for the variables */
00924             if ((!empty)&&(SimplexNRows(&lp)>0)) /* In extreme cases the simplex tableau can be empty 
00925                                                     and then nothings can be reduced*/
00926               { 
00927                 /* Store the original box to check the actual reduction */
00928                 CopyBox(&b_orig,b);
00929 
00930                 #if (_SIMPLEX_ENGINE!=_CLP) /* in CLP Reset Simplex has no effect */
00931                   ResetSimplex(&lp);
00932                 #endif
00933 
00934                 for(i=0;((boxOK)&&(i<cs->nvariables));i++)
00935                   {
00936                     /* The crop takes care of reducing the ranges of the dummy 
00937                        variables in function of the non dummy ones (system,
00938                        secondary and cartesian).
00939                     */
00940 
00941                     if ((cs->varType[i]&varMask)&&(!SimplexColEmpty(i,&lp)))
00942                       {
00943                         /*Reduce the ranges for variable 'i'*/
00944                         e=ReduceRange(epsilon,safe_simplex,i,b,&lp);
00945                         boxOK=(e==REDUCED_BOX); 
00946                       }             
00947                   }
00948 
00949                 /* Analize the output out of the range reduction */
00950                 if (boxOK)
00951                   {
00952                     /* Compute the minimum reduction ratio for all ranges. The smaller
00953                        the reductin ratio, the maximal the box shrink for that dimension*/
00954                     mi_r=1.0;
00955                     ma_s=0.0;
00956                     for(i=0;i<cs->nvariables;i++)
00957                       {
00958                         if (cs->notDummyVar[i])
00959                           {
00960                             size=IntervalSize(GetBoxInterval(i,b));
00961                             if (size>ma_s) ma_s=size;
00962 
00963                             reduction=size/IntervalSize(GetBoxInterval(i,&b_orig));
00964                             if (reduction<mi_r) mi_r=reduction; 
00965                           }
00966                       }
00967 
00968                     /* If the output box is fully included in the input one this means
00969                        the box includes a solution (for sure) */
00970                     if ((ma_s<lr2tm_q)&&(ma_s<lr2tm_s)&&
00971                         (BoxInclusion(cs->systemVar,b,&b_orig)))
00972                       {
00973                         hasSolution=TRUE;
00974                         #if(!_USE_MPI)
00975                           fprintf(stderr,"(>!<)");
00976                         #endif
00977                       }
00978 
00979                     small=(ma_s<=smallSigma);
00980                     significantReduction=(mi_r<rho); 
00981                   }
00982                 else
00983                   {
00984                     empty=(e==EMPTY_BOX);
00985                     err=(e==ERROR_IN_PROCESS);
00986                   }
00987 
00988                 DeleteBox(&b_orig);
00989               }
00990 
00991             repeatLoop=((!empty)&&(!err)&&(!small)&&(significantReduction));
00992             
00993             SimplexDelete(&lp);
00994 
00995             #if (_DEBUG>2)
00996             if (empty)
00997               printf("    Empty\n");
00998             else
00999               {
01000                 if (err)
01001                   printf("    Simplex Error\n");
01002                 else
01003                   {
01004                     printf("  OutputBox: "); PrintBox(stdout,b);
01005                     printf("  Reduction ->  %f\n",mi_r);
01006                   
01007                     printf("  Size after reduction: %g\n ",GetBoxSize(cs->systemVar,b));
01008                     printf("  Volume after reduction: %g\n ",GetBoxVolume(cs->systemVar,b));
01009                   
01010                     if (significantReduction)
01011                       printf("    Large enough reduction-> Try again all equations\n");
01012                     else
01013                       printf("    Not enough reduction.\n");
01014                   }
01015               }
01016             #endif 
01017 
01018           } /* end if not empty after */
01019 
01020       } while(repeatLoop);
01021       
01022       if (err)
01023         e=ERROR_IN_PROCESS;
01024       else
01025         {
01026           if (empty)
01027             e=EMPTY_BOX;
01028           else
01029             {
01030               /* If at least on step was a contraction this means
01031                  there is a solution inside the box*/
01032               if (hasSolution)
01033                 e=REDUCED_BOX_WITH_SOLUTION; 
01034               else
01035                 e=REDUCED_BOX;
01036             }
01037         }
01038 
01039       return(e);
01040     }
01041 }
01042 
01043 /*
01044   This procedure is called just after using ReduceBox to analyzed what
01045   happened with the box and what to do next.ç
01046 
01047   'c' is the return code out of Reduce Box
01048 
01049   If the box is small (max side size smaller than sigma), we consider it 
01050   a solution and we store it in the list 'sol' (if defined), we save 
01051   the solution into 'f_out' (if defined).
01052   
01053   Otherwise, we split the box in two sub-boxes and we store them in list 'boxes'
01054   The dimension along which the box is splitte is determined  according to 
01055   parameter 'error_split'. The two sub-boxes are added to 'boxes' in the first
01056   of in the last position according to parameter 'depth_first'.
01057 */
01058 void PostProcessBox(Tparameters *p,
01059                     unsigned int c,
01060                     FILE *f_out,
01061                     Tlist *sol,
01062                     Theap *boxes,Tbox *b,
01063                     TCuikSystem *cs)
01064 {
01065   boolean empty,small;
01066   Tbox b_orig;
01067   double sigma;
01068 
01069   empty=(c==EMPTY_BOX);
01070         
01071   if (empty)
01072     {
01073       NewEmptyBox(&(cs->st));
01074       #if (_DEBUG>1)
01075         printf("  The box is empty -> deleted\n");
01076       #endif
01077       #if (_DEBUG>0)
01078         fprintf(stderr,"e\n");
01079       #endif
01080     }
01081   else
01082     {
01083       /* c==REDUCED_BOX or c==REDUCED_BOX_WITH_SOLUTION or c==ERROR_IN_PROCESS*/
01084       #if (_DEBUG>1)
01085         printf("  Resulting box: ");
01086         PrintBox(stdout,b);
01087       #endif
01088       #if (_DEBUG>0)
01089         fprintf(stderr,"<%g %g>",
01090                 GetBoxVolume(cs->systemVar,b),
01091                 GetBoxSize(cs->systemVar,b));
01092       #endif  
01093         
01094       /* We initialize a box in the original system and set the default ranges
01095          (ranges in case the variable in the original system is not in the
01096          simplified one... this is not likely to occur here but in the system
01097          to sybsystem relation but in this way the interface is the same)*/
01098       BoxFromVariables(&b_orig,&(cs->orig_variables)); 
01099       UpdateOriginalFromSimple(b,&b_orig,cs->orig2sd);
01100       #if (_DEBUG>1)
01101         printf("  Original box: ");
01102         PrintBox(stdout,&b_orig);
01103       #endif
01104 
01105       sigma=GetParameter(CT_SIGMA,p);
01106 
01107       /*The original system can have variables not included in the simplified one. For instance, 
01108         variables not in the system equations due to the particular constants of the problem under
01109         analysis are eliminated, even though they appear in dummy equations (this is common
01110         when ROT_REP=1, see link.h). Those removed variables are never reduced and thus,
01111         the original box never reduces below sigma. This is why we use the simplified box
01112         (i.e., the one we actually reduce) to assess whether or not we have a solution. */
01113       small=(GetBoxSize(cs->systemVar,b)<=sigma);
01114 
01115       if (small)
01116         {
01117 
01118           #if (_DEBUG>1)
01119             printf("  The box is a solution (size %g vs [%g]) ->add to the list of solutions\n",
01120                    GetBoxSize(cs->orig_systemVar,&b_orig),sigma);
01121           #endif
01122 
01123           NewSolutionBox((c==REDUCED_BOX_WITH_SOLUTION),
01124                          GetBoxVolume(cs->orig_systemVar,&b_orig),
01125                          GetBoxDiagonal(cs->orig_systemVar,&b_orig),
01126                          &(cs->st));
01127           
01128           if(c==ERROR_IN_PROCESS)
01129             NewRBError(&(cs->st));
01130  
01131           #if (_DEBUG>0)
01132             if(c==REDUCED_BOX_WITH_SOLUTION)
01133               fprintf(stderr,"S\n");
01134             else
01135               fprintf(stderr,"s\n");
01136           #endif        
01137               
01138           
01139           if (f_out!=NULL)
01140             {
01141               if(c==ERROR_IN_PROCESS)
01142                 fprintf(f_out," E");
01143               
01144               fprintf(f_out," %3u (err:%g",
01145                       GetNSolutionBoxes(&(cs->st)),
01146                       ErrorInSolution(&b_orig,cs));
01147               
01148               if (cs->searchMode==MINIMIZATION_SEARCH)
01149                 fprintf(f_out," min:%g",EvaluateEqMin((void *)b,(void *)cs));
01150 
01151               fprintf(f_out," tm:%g):",GetElapsedTime(&(cs->st)));
01152 
01153               if (c==REDUCED_BOX_WITH_SOLUTION)
01154                 fprintf(f_out," <S> ");
01155 
01156               /*The output does not include the dummy variables (they are 
01157                 not relevant any more)*/
01158               PrintBoxSubset(f_out,cs->orig_notDummyVar,cs->orig_varNames,&b_orig); 
01159               fflush(f_out);          
01160             }
01161           if (sol!=NULL)
01162             {
01163               Tbox *sb;
01164 
01165               NEW(sb,1,Tbox); 
01166 
01167               CopyBox(sb,&b_orig);
01168 
01169               AddLastElement((void *)sb,sol);
01170             }
01171 
01172           /*If we want to ad box to a solution list, we have to copy 'b' 
01173             somewhere else ('b' is delete after this function !)*/
01174         }
01175       else
01176         {
01177           /* Non empty large box or error in ReduceBox */
01178 
01179           Tbox b1,b2;
01180           unsigned int d;
01181 
01182           #if (_DEBUG>1)
01183             printf("  Box size : %g vs. %g\n",GetBoxSize(cs->orig_systemVar,&b_orig),sigma);
01184             printf("  The box has to be splitted (and deleted)\n");
01185           #endif
01186 
01187           NewSplittedBox(&(cs->st));
01188 
01189           d=ComputeSplitDimInt(p,b,cs);
01190 
01191           SplitBox(d,CUT_POINT,&b1,&b2,b);
01192 
01193           #if (_DEBUG>1)
01194             printf("  Splitting along dimension %u (internal)\n",d);
01195             if (cs->searchMode==MINIMIZATION_SEARCH)
01196               printf("      Box penalgy : %g\n",EvaluateEqMin((void *)&b1,(void *)cs));
01197             printf("        SubBox:"); PrintBox(stdout,&b1);
01198             if (cs->searchMode==MINIMIZATION_SEARCH)
01199               printf("      Box penalty : %g\n",EvaluateEqMin((void *)&b2,(void *)cs));
01200             printf("        SubBox:"); PrintBox(stdout,&b2);
01201           #endif
01202 
01203           AddBox2HeapOfBoxes(&b1,boxes);
01204           AddBox2HeapOfBoxes(&b2,boxes);
01205           DeleteBox(&b1);
01206           DeleteBox(&b2);
01207          
01208           if (c==ERROR_IN_PROCESS)
01209             {
01210               #if (_DEBUG>0)
01211                 fprintf(stderr,"E[%u]\n",d);
01212               #endif
01213               #if (_DEBUG>1)
01214                 printf("  Splitted due to simplex error\n");
01215               #endif
01216               NewRBError(&(cs->st));
01217             }
01218           #if (_DEBUG>0)
01219           else
01220             fprintf(stderr,"b[%u]\n",d);
01221           #endif
01222         }
01223 
01224       DeleteBox(&b_orig);  
01225     }
01226 }
01227 
01228 void CSRemoveUnusedVars(Tparameters *p,TCuikSystem *cs)
01229 {
01230   unsigned int i,vt;
01231   double epsilon;
01232 
01233   epsilon=GetParameter(CT_EPSILON,p);
01234 
01235   /*We proceed back to front because removing a variable change the
01236     indexes of variables above it.*/
01237   i=NVariables(&(cs->variables));
01238   while(i>0)
01239     {
01240       i--;
01241       vt=GetVariableTypeN(i,&(cs->variables));
01242       //if (((vt==DUMMY_VAR)&&(!UsedVarInNonDummyEquations(i,&(cs->equations))))||
01243       //  ((vt!=DUMMY_VAR)&&(!UsedVarInEquations(i,&(cs->equations)))))
01244       if (((vt==DUMMY_VAR)&&(!UsedVarInNonDummyEquations(i,&(cs->equations))))||
01245           ((vt!=SYSTEM_VAR)&&(!UsedVarInEquations(i,&(cs->equations)))))
01246         {
01247           /* ... Therefore, we can still have dummy equations with the non-used variables*/
01248           RemoveEquationsWithVar(epsilon,i,&(cs->equations)); 
01249           RemoveVariable(i,&(cs->variables));
01250         }
01251     }
01252 }
01253 
01254 boolean CSRemoveVarsWithCtRange(Tparameters *p,
01255                                 boolean *replaced,TLinearConstraint *lc,
01256                                 Tbox *borig,TCuikSystem *cs)
01257 {
01258   boolean found,hold;
01259   unsigned int nv,origID1;
01260   unsigned int id1;
01261   char *name1;
01262   double epsilon;
01263   double ct2;
01264   Tinterval *range;
01265   
01266   epsilon=GetParameter(CT_EPSILON,p);
01267 
01268   hold=TRUE;
01269 
01270   do {
01271     found=FALSE;
01272 
01273     /* A variable with a ct range can be removed */
01274     nv=NVariables(&(cs->variables));
01275     id1=0;
01276     while((!found)&&(id1<nv))
01277       {
01278         name1=GetVariableName(GetVariable(id1,&(cs->variables)));
01279         origID1=GetVariableID(name1,&(cs->orig_variables));
01280         if (origID1==NO_UINT)
01281           Error("Undefined ID1 in CSRemoveVarsWithCtRange");
01282 
01283         range=GetBoxInterval(origID1,borig);
01284         if (IntervalSize(range)==0)
01285           {
01286             ct2=LowerLimit(range); /* ==UpperLimit(range) */
01287             found=TRUE;
01288           }
01289         else
01290           id1++;
01291       }
01292 
01293     /*if we found something to simplify, apply it to the rest of equations
01294       (this creates a new set of equations that replaces the previous one)*/
01295     if (found)
01296       {
01297         replaced[origID1]=TRUE;
01298         AddCt2LinearConstraint(ct2,&(lc[origID1]));
01299 
01300         #if (_DEBUG>5) 
01301           printf("Ct Range Replacement: %s [%u-%u] ->%.12g\n",name1,origID1,id1,ct2);
01302         #endif
01303             
01304         if (hold)
01305           {
01306             TLinearConstraint lc;
01307 
01308             InitLinearConstraint(&lc);
01309             AddCt2LinearConstraint(ct2,&lc);
01310             hold=ReplaceVariableInEquations(epsilon,id1,&lc,&(cs->equations));
01311             DeleteLinearConstraint(&lc);
01312             RemoveVariable(id1,&(cs->variables));
01313             
01314             #if (_DEBUG>6)
01315             if(hold)
01316               {
01317                 char **varNames;
01318                 
01319                 
01320                 printf("%%=======================================================\n");
01321                 printf("%% One less variable (ct range)\n"); 
01322                 printf("%%****************************************\n");
01323                 PrintVariables(stdout,&(cs->variables));
01324                 
01325                 nv=NVariables(&(cs->variables));
01326                 NEW(varNames,nv,char *);
01327                 GetVariableNames(varNames,&(cs->variables));
01328                 PrintEquations(stdout,varNames,&(cs->equations));
01329                 free(varNames);
01330               }
01331             #endif
01332           }
01333       }
01334   } while((hold)&&(found));
01335 
01336   return(hold);
01337 }
01338 
01339 boolean CSRemoveLCVars(Tparameters *p,unsigned int nTerms,boolean *changed,
01340                        boolean *replaced,TLinearConstraint *lc,
01341                        Tbox *borig,TCuikSystem *cs)
01342 {
01343   boolean found,hold;
01344   unsigned int m,i,j,nv,neq,origID,origID1;
01345   Tequation *eq;
01346   unsigned int id;
01347   char *name,*name1;
01348   double epsilon;
01349   Tvariable *v;
01350   TLinearConstraint lcr,lcc;
01351   boolean *systemVars;
01352   Tinterval error;
01353   unsigned int simplificationLevel;
01354   #if (_DEBUG>5) 
01355     char **varNamesO;
01356 
01357     nv=NVariables(&(cs->orig_variables));
01358     NEW(varNamesO,nv,char *);
01359     GetVariableNames(varNamesO,&(cs->orig_variables));
01360   #endif
01361 
01362   nv=NVariables(&(cs->variables));
01363   NEW(systemVars,nv,boolean);
01364   for(i=0;i<nv;i++)
01365     systemVars[i]=IsSystemVariable(i,&(cs->variables));
01366 
01367   epsilon=GetParameter(CT_EPSILON,p);
01368   simplificationLevel=(unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p));
01369 
01370   *changed=FALSE;
01371   hold=TRUE;
01372 
01373   found=FALSE;
01374   i=0;
01375   neq=NEquations(&(cs->equations));
01376   while((!found)&&(i<neq))
01377     {
01378       eq=GetEquation(i,&(cs->equations));
01379 
01380       found=IsSimplificable(simplificationLevel,nTerms,systemVars,&id,&lcr,eq); /* 't' is the type of simplification*/
01381       if (!found)
01382         i++;
01383     }
01384 
01385   /*if we found something to simplify, apply it to the rest of equations
01386     (this creates a new set of equations that replaces the previous one)*/
01387   if (found)
01388     {
01389       *changed=TRUE;
01390 
01391       /* Translate the variables identifiers from local to global */
01392       v=GetVariable(id,&(cs->variables));
01393       name=GetVariableName(v);
01394       origID=GetVariableID(name,&(cs->orig_variables));
01395       if (origID==NO_UINT)
01396         Error("Undefined ID1 in CSRemoveLCVars");
01397 
01398       /* Translate the 'lcr' linear constraint that refers to the cuiksystem
01399          in the current state of simplification to the original system */
01400       m=GetNumTermsInLinearConstraint(&lcr);
01401       for(i=0;i<m;i++)
01402         {
01403           v=GetVariable(GetLinearConstraintVariable(i,&lcr),&(cs->variables));
01404           name1=GetVariableName(v);
01405           origID1=GetVariableID(name1,&(cs->orig_variables));
01406           if (origID1==NO_UINT)
01407             Error("Undefined ID in CSRemoveLCVars");
01408           AddTerm2LinearConstraint(origID1,
01409                                    GetLinearConstraintCoefficient(i,&lcr),
01410                                    &(lc[origID]));
01411         }
01412       GetLinearConstraintError(&error,&lcr);
01413       if (IntervalSize(&error)>ZERO)
01414         Error("Linear constraint used for variable replacement must have ct right-hand");
01415       AddCt2LinearConstraint(-IntervalCenter(&error),&(lc[origID]));
01416 
01417       replaced[origID]=TRUE;
01418 
01419       #if (_DEBUG>5) 
01420         printf("Var Replacement: %s[%u-%u]->",name,origID,id);
01421         PrintLinearConstraint(stdout,FALSE,varNamesO,&(lc[origID]));
01422       #endif
01423 
01424       CopyLinearConstraint(&lcc,&(lc[origID]));
01425       AddTerm2LinearConstraint(origID,-1.0,&lcc);
01426       hold=CropLinearConstraint(ZERO,borig,&lcc);
01427       if (!hold)
01428         printf("\nNon intersecting ranges\n");
01429       DeleteLinearConstraint(&lcc);
01430 
01431       /*If origID was used for the replacement of another variable
01432         we have to propagate the replacement of origID1 to this other
01433         variable*/
01434       nv=NVariables(&(cs->orig_variables));
01435       for(j=0;((hold)&&(j<nv));j++)
01436         {
01437           if ((replaced[j])&&(LinearConstraintIncludes(origID,&(lc[j]))))
01438             {
01439               TLinearConstraint ltmp;
01440               double ct;
01441 
01442               ct=RemoveTermFromLinearConstraint(origID,&(lc[j]));
01443               CopyLinearConstraint(&ltmp,&(lc[origID]));
01444               ScaleLinearConstraint(ct,&ltmp);
01445               AddLinearConstraints(&ltmp,&(lc[j]));
01446               
01447               CopyLinearConstraint(&lcc,&(lc[j]));
01448               AddTerm2LinearConstraint(j,-1.0,&lcc);
01449               hold=CropLinearConstraint(ZERO,borig,&lcc);
01450               if (!hold) 
01451                 printf("\nNon intersecting ranges\n");
01452               DeleteLinearConstraint(&lcc);
01453             }
01454         }
01455 
01456       if (hold)
01457         {
01458           hold=ReplaceVariableInEquations(epsilon,id,&lcr,&(cs->equations));
01459           RemoveVariable(id,&(cs->variables));
01460 
01461           #if (_DEBUG>6)
01462             if(hold)
01463               {
01464                 char **varNames;
01465                 
01466                 printf("%%=======================================================\n");
01467                 printf("%% One less variable (replaced)\n"); 
01468                 printf("%%****************************************\n");
01469                 PrintVariables(stdout,&(cs->variables));
01470                 
01471                 nv=NVariables(&(cs->variables));
01472                 NEW(varNames,nv,char *);
01473                 GetVariableNames(varNames,&(cs->variables));
01474                 PrintEquations(stdout,varNames,&(cs->equations));
01475                 free(varNames);
01476               }
01477           #endif
01478         }
01479 
01480       DeleteLinearConstraint(&lcr);
01481     }
01482   #if (_DEBUG>5)
01483     free(varNamesO);
01484   #endif
01485   free(systemVars);
01486   return(hold);
01487 }
01488 
01489 /*
01490   Simplifies a CuikSystem removing variables have constant value and those
01491   that depend linearly on other variables. Moreover, a primitive (but numerically
01492   save) form of Gaussian elimination is performed to remove as more variables
01493   and equations as possible.
01494   More elaborate forms of system simplifications are not implemented because they
01495   result in numerical errors (that can change the system solutions).
01496   The output mappings give information about how the original and the simplified
01497   systems are related.
01498 
01499   This is part of the UpdateCuikSystem.
01500 */
01501 boolean SimplifyCuikSystem(Tparameters *p,TCuikSystem *cs)
01502 {
01503 
01504   unsigned int i,nv,nvn,newVarID;
01505   boolean *replaced;
01506   TLinearConstraint *lc,lcS;
01507   boolean changed,anyChange,hold;
01508   char *name1;
01509   double epsilon;
01510   Tbox borig,bsimp;
01511   unsigned int nTerms,m,k;
01512   Tinterval error;
01513   unsigned int simplificationLevel;
01514 
01515   epsilon=GetParameter(CT_EPSILON,p);
01516   simplificationLevel=(unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p));
01517 
01518   #if(_DEBUG>5)
01519     unsigned int iteration;
01520   #endif
01521 
01522   /* Get a copy of the original cuiksystem */
01523   CopyVariables(&(cs->variables),&(cs->orig_variables));
01524   CopyEquations(&(cs->equations),&(cs->orig_equations));
01525 
01526   nv=NVariables(&(cs->orig_variables)); /* number of variables in the original system */
01527 
01528   NEW(replaced,nv,boolean);
01529   NEW(lc,nv,TLinearConstraint);
01530   
01531   BoxFromVariables(&borig,&(cs->orig_variables)); /*original ranges to be possibly reduced during
01532                                                     simplification */
01533   for(i=0;i<nv;i++)
01534     {
01535       replaced[i]=FALSE;
01536       InitLinearConstraint(&(lc[i]));
01537     }
01538 
01539   hold=TRUE; /* in the simplification process we can discover that the input system
01540                 is inconsitent (i.e., that it does not hold)*/
01541  
01542   if (simplificationLevel>0) /* For detailed debug systems are not simplified */
01543     { 
01544       #if(_DEBUG>5)
01545         iteration=0;
01546       #endif
01547 
01548       CSRemoveUnusedVars(p,cs);
01549       hold=CSRemoveVarsWithCtRange(p,replaced,lc,&borig,cs);
01550     
01551       anyChange=TRUE; /* Set to TRUE to trigger the simplification process */
01552       while((hold)&&(anyChange))
01553         {
01554           anyChange=FALSE; /* Will be set to TRUE if at least one variable is removed
01555                               in the loop below */
01556           nTerms=0; /* First we try to remove ct variables, then scaled ones,i.e., we
01557                        progressivelly increase the number of terms used in the
01558                        replacements. */
01559           while((hold)&&(nTerms<=MAX_TERMS_SIMP)) /*hard-coded maximum complexity of the simplifications*/
01560             {
01561               hold=CSRemoveLCVars(p,nTerms,&changed,replaced,lc,&borig,cs);
01562               anyChange=((anyChange)||(changed));
01563               if (changed)
01564                 nTerms=0;
01565               else
01566                 nTerms++;
01567             }
01568 
01569           /* At this point no more ct or scaled varibles can be removed. Try to
01570              simplify the problem via Gaussian elimination*/
01571           if ((hold)&&(anyChange))
01572             {
01573               anyChange=FALSE;
01574               do {
01575                 changed=GaussianElimination(&(cs->equations));
01576                 anyChange=((anyChange)||(changed));
01577               } while (changed);
01578 
01579               #if (_DEBUG>6)
01580               {
01581                 char **varNames;
01582                 unsigned int nvg;
01583 
01584                 printf("%%=======================================================\n");
01585                 printf("%% After gaussian elimination\n"); 
01586                 printf("%%****************************************\n");
01587                 PrintVariables(stdout,&(cs->variables));
01588               
01589                 nvg=NVariables(&(cs->variables));
01590                 NEW(varNames,nvg,char *);
01591                 GetVariableNames(varNames,&(cs->variables));
01592                 PrintEquations(stdout,varNames,&(cs->equations));
01593                 free(varNames);
01594               }
01595               #endif
01596             }
01597         } 
01598     }
01599 
01600   #if(_DEBUG>4)
01601     if (hold)
01602       {
01603         char **varNames;
01604         unsigned int nvg;
01605 
01606         printf("%%=======================================================\n");
01607         printf("%%FINAL SIMPLIFIED SYSTEM\n"); 
01608         printf("%%****************************************\n");
01609         PrintVariables(stdout,&(cs->variables));
01610         
01611         nvg=NVariables(&(cs->variables));
01612         NEW(varNames,nvg,char *);
01613         GetVariableNames(varNames,&(cs->variables));
01614         PrintEquations(stdout,varNames,&(cs->equations));
01615         free(varNames);
01616       }
01617     else
01618       printf("Inconsistent input system\n");
01619   #endif
01620 
01621   if (hold)
01622     {
01623       /* Get a copy of the simplified but not still dummified cuiksystem */
01624       CopyVariables(&(cs->simp_variables),&(cs->variables));
01625       CopyEquations(&(cs->simp_equations),&(cs->equations));
01626 
01627       /*The final step is to dummify the cuiksystem*/
01628       DummifyCuikSystem(p,cs);
01629 
01630       /*define the mappings from the gathered information*/
01631 
01632       NEW(cs->orig2sd,1,Tmapping);
01633       NEW(cs->orig2s,1,Tmapping);
01634 
01635       InitMapping(&(cs->orig_variables),&(cs->variables),cs->orig2sd);
01636       InitMapping(&(cs->orig_variables),&(cs->simp_variables),cs->orig2s);
01637 
01638 
01639       /* now we complement the default initialization with the replacements computed above */
01640       for(i=0;i<nv;i++)
01641         {
01642           if (replaced[i])
01643             {
01644               m=GetNumTermsInLinearConstraint(&(lc[i]));
01645               InitLinearConstraint(&lcS);
01646               for(k=0;k<m;k++)
01647                 {
01648                   name1=GetVariableName(GetVariable(GetLinearConstraintVariable(k,&(lc[i])),&(cs->orig_variables)));
01649                   newVarID=GetVariableID(name1,&(cs->variables));
01650                   
01651                   AddTerm2LinearConstraint(newVarID,GetLinearConstraintCoefficient(k,&(lc[i])),&lcS);
01652                 }
01653               GetLinearConstraintError(&error,&(lc[i]));
01654               AddCt2LinearConstraint(-IntervalCenter(&error),&lcS);
01655               
01656               SetOriginalVarRelation(i,&lcS,cs->orig2sd);
01657               SetOriginalVarRelation(i,&lcS,cs->orig2s);
01658 
01659               DeleteLinearConstraint(&lcS);
01660             }
01661         }
01662 
01663       SimpleFromOriginal(&borig,&bsimp,cs->orig2sd);
01664       nvn=NVariables(&(cs->variables)); 
01665       for(i=0;i<nvn;i++)
01666         SetVariableInterval(GetBoxInterval(i,&bsimp),GetVariable(i,&(cs->variables)));
01667       DeleteBox(&bsimp);
01668     }
01669 
01670   DeleteBox(&borig);
01671 
01672   /* free the information used for the mapping */
01673   for(i=0;i<nv;i++)
01674     DeleteLinearConstraint(&lc[i]);
01675   free(replaced);
01676   free(lc);
01677 
01678   return(hold);
01679 }
01680 
01681 /*
01682   Removes the information stored in the cuiksystem during the update
01683 */
01684 void UnUpdateCuikSystem(TCuikSystem *cs)
01685 {
01686   
01687   if (cs->updated)
01688     {
01689       /*Removes cached information that is used during solving*/
01690      
01691       /*Firt the box sorting information*/
01692       if (cs->searchMode==MINIMIZATION_SEARCH)
01693         DeleteEquation(&(cs->eqMin));
01694 
01695       /*Now the information about the simplified+dummified system*/
01696       if (cs->orig2sd!=NULL)
01697         {
01698           DeleteMapping(cs->orig2sd);
01699           free(cs->orig2sd);
01700           cs->orig2sd=NULL;
01701         }
01702 
01703       cs->nequations=0;
01704       cs->nvariables=0;  
01705       if (cs->systemVar!=NULL) 
01706         free(cs->systemVar);
01707       cs->systemVar=NULL;
01708       if (cs->notDummyVar!=NULL)
01709         free(cs->notDummyVar);
01710       cs->notDummyVar=NULL;
01711       if (cs->varType!=NULL)
01712         free(cs->varType);
01713       cs->varType=NULL;
01714 
01715       DeleteEquations(&(cs->equations));
01716       DeleteVariables(&(cs->variables));
01717 
01718       /*Now remove the information about the simplified system*/
01719       if (cs->orig2s!=NULL)
01720         {
01721           DeleteMapping(cs->orig2s);
01722           free(cs->orig2s);
01723           cs->orig2s=NULL;
01724         }
01725       DeleteSimpCuikSystemJacobian(cs);
01726 
01727       cs->simp_nequations=0;
01728       cs->simp_nvariables=0;;
01729       cs->simp_nee=0;
01730 
01731       DeleteEquations(&(cs->simp_equations));
01732       DeleteVariables(&(cs->simp_variables));
01733 
01734       /*Finally remove the information about the original system*/ 
01735       cs->orig_nequations=0;
01736       cs->orig_nvariables=0;  
01737       if (cs->orig_systemVar!=NULL) 
01738         free(cs->orig_systemVar);
01739       cs->orig_systemVar=NULL;
01740       if (cs->orig_notDummyVar!=NULL)
01741         free(cs->orig_notDummyVar);
01742       cs->orig_notDummyVar=NULL;
01743 
01744       free(cs->orig_varNames);
01745       cs->orig_varNames=NULL;
01746 
01747       /*Mark the system as not updated*/
01748       cs->updated=FALSE;
01749     }
01750 }
01751 
01752 /*
01753   Simplifies the CuikSystem and caches information that is useful during 
01754   solving (cached->faster access).
01755 */
01756 boolean UpdateCuikSystem(Tparameters *p,TCuikSystem *cs)
01757 {
01758   boolean hold=TRUE;
01759 
01760   if (!cs->updated)
01761     { 
01762       unsigned int j;
01763 
01764       /* we update even if we have no equations to be able to deal
01765          with systems without equations (non constrained problems)
01766          In this case cuik is a standard approximated cell decomposition 
01767          approach
01768        */
01769       hold=SimplifyCuikSystem(p,cs);
01770       
01771       if (hold)
01772         {
01773           /* Update the information in the original system */
01774           cs->orig_nequations=NEquations(&(cs->orig_equations));
01775           cs->orig_nvariables=NVariables(&(cs->orig_variables));
01776 
01777           if (cs->orig_nvariables==0)
01778             {
01779               cs->orig_systemVar=NULL;
01780               cs->orig_notDummyVar=NULL;
01781               cs->orig_varNames=NULL;
01782             }
01783           else
01784             {
01785               NEW(cs->orig_systemVar,cs->orig_nvariables,boolean);
01786               NEW(cs->orig_notDummyVar,cs->orig_nvariables,boolean);
01787           
01788               for(j=0;j<cs->orig_nvariables;j++)
01789                 {
01790                   cs->orig_systemVar[j]=IsSystemVariable(j,&(cs->orig_variables));
01791                   cs->orig_notDummyVar[j]=!IsDummyVariable(j,&(cs->orig_variables));
01792                 }
01793 
01794               NEW(cs->orig_varNames,cs->orig_nvariables,char *);
01795               GetVariableNames(cs->orig_varNames,&(cs->orig_variables));
01796             }
01797 
01798           /* Update the simplifed cuiksystem */
01799           cs->simp_nequations=NEquations(&(cs->simp_equations));
01800           cs->simp_nvariables=NVariables(&(cs->simp_variables));
01801           cs->simp_nee=NEqualityEquations(&(cs->simp_equations));
01802 
01803           ComputeSimpCuikSystemJacobian(cs);
01804 
01805           /* Update the information in the simplified+dummified cuiksystem*/
01806           cs->nequations=NEquations(&(cs->equations));
01807           cs->nvariables=NVariables(&(cs->variables));
01808 
01809           cs->empty=((cs->nvariables==0)||(cs->nequations==0));
01810 
01811           if ((cs->nequations>0)&&(cs->nvariables==0))
01812             Error("System with equations but without variables !!");
01813 
01814           if (cs->nvariables==0)
01815             {
01816               cs->systemVar=NULL;
01817               cs->notDummyVar=NULL;
01818               cs->varType=NULL;
01819             }
01820           else
01821             {
01822               NEW(cs->systemVar,cs->nvariables,boolean);
01823               NEW(cs->notDummyVar,cs->nvariables,boolean);
01824               NEW(cs->varType,cs->nvariables,unsigned int);
01825           
01826               for(j=0;j<cs->nvariables;j++)
01827                 {
01828                   cs->systemVar[j]=IsSystemVariable(j,&(cs->variables));
01829                   cs->notDummyVar[j]=!IsDummyVariable(j,&(cs->variables));
01830                   cs->varType[j]=GetVariableTypeN(j,&(cs->variables));
01831                 }
01832             }
01833 
01834           /* Mark the system as updated */
01835           cs->updated=TRUE;
01836         }
01837       
01838       /* Update the information about the sorting criteria for boxes */
01839       if (cs->searchMode==MINIMIZATION_SEARCH)
01840         {
01841           if (GetNumMonomials(&(cs->orig_eqMin))==0)
01842             {
01843               ResetEquation(&(cs->orig_eqMin));
01844               cs->searchMode=DEPTH_FIRST_SEARCH;
01845             }
01846           else
01847             RewriteEquation(GetParameter(CT_EPSILON,p),
01848                             cs->orig2sd,&(cs->eqMin),&(cs->orig_eqMin));
01849         }
01850     }
01851 
01852   return(hold);
01853 }
01854 
01855 /*
01856   Selects one dimension along which to split box 'b'. The dimension can
01857   be selected according to the size or according to the error that each
01858   variable induce in each equation.
01859   The output is a index in the simplified system
01860  */
01861 unsigned int ComputeSplitDimInt(Tparameters *p,Tbox *b,TCuikSystem *cs)
01862 {
01863   
01864   UpdateCuikSystem(p,cs);
01865 
01866   if (cs->nvariables==0)
01867     {
01868       Error("Splitting an empty cuiksystem");
01869       return(NO_UINT);
01870     }
01871   else
01872     {
01873       unsigned int i;
01874       Tinterval *is;
01875       double *splitDim;
01876       unsigned int *d;
01877       unsigned int n;
01878       double m,s;
01879       unsigned int splitType;
01880 
01881       splitType=(unsigned int)(GetParameter(CT_SPLIT_TYPE,p));
01882 
01883       NEW(splitDim,cs->nvariables,double);
01884       NEW(d,cs->nvariables,unsigned int);
01885 
01886       is=GetBoxIntervals(b);
01887 
01888       if ((cs->nequations>0)&&(splitType==1))
01889         {
01890           for(i=0;i<cs->nvariables;i++)
01891             splitDim[i]=0.0;
01892       
01893           /*Add the error contribution*/
01894           for(i=0;i<cs->nequations;i++)
01895             UpdateSplitWeight(i,splitDim,b,&(cs->equations));
01896 
01897           /*Do not split along unbounded variables*/
01898           for(i=0;i<cs->nvariables;i++)
01899             {
01900               if(IntervalSize(&(is[i]))>=INF)
01901                 splitDim[i]=0.0;
01902             }
01903         }
01904       else
01905         {
01906           if (splitType!=2) 
01907             {
01908               /*size-based split or error-based split without any equation*/
01909               for(i=0;i<cs->nvariables;i++)
01910                 {
01911                   s=IntervalSize(&(is[i]));
01912                   if (s<INF)
01913                     splitDim[i]=s;
01914                   else
01915                     splitDim[i]=0.0;
01916                 }
01917             }
01918           else
01919             {
01920               /*splitType==2 -> random selection of the split dimension */ 
01921               double epsilon;
01922 
01923               epsilon=GetParameter(CT_EPSILON,p);
01924 
01925               for(i=0;i<cs->nvariables;i++)
01926                 {
01927                   s=IntervalSize(&(is[i]));
01928                   if ((s>10*epsilon)&&(s<INF))
01929                     splitDim[i]=1.0;
01930                   else
01931                     splitDim[i]=0.0;
01932                 }
01933               
01934             }
01935         }
01936 
01937       m=-1.0;
01938       n=0;
01939       for(i=0;i<cs->nvariables;i++)
01940         {
01941           if (cs->systemVar[i])
01942             {
01943               if (splitDim[i]>m)
01944                 {
01945                   m=splitDim[i];
01946                   d[0]=i;
01947                   n=1;
01948                 }
01949               else
01950                 {
01951                   if (splitDim[i]==m)
01952                     {
01953                       d[n]=i;
01954                       n++;
01955                     }
01956                 }
01957             }
01958         
01959         }
01960  
01961       if (n>0) 
01962         i=d[randomMax(n-1)];
01963       else
01964         {
01965           Warning("There is no way where to bisect the box");
01966           i=randomMax(cs->nvariables-1);
01967         }
01968 
01969       free(d);
01970       free(splitDim);
01971 
01972       return(i);
01973     }
01974 }
01975 
01976 void SaveCSState(char *fname,Tlist *lb,TCuikSystem *cs)
01977 {  
01978   FILE *f;
01979   char *tmpName;
01980   double tm;
01981 
01982   /*We initially save to a temporary file and then we rename it
01983     This increases the atomiticy of this operation (if the state
01984     file is corrupted the recovery operation would fail) */
01985   NEW(tmpName,strlen(fname)+10,char);
01986   sprintf(tmpName,"%s.tmp",fname);
01987   
01988   /*open in binary mode*/
01989   f=fopen(tmpName,"wb");
01990   if (!f)
01991     Error("Could not open file for saving CSState");
01992 
01993   tm=GetElapsedTime(&(cs->st));
01994   fwrite(&tm,sizeof(double),1,f);
01995   SaveStatistics(f,&(cs->st));
01996   SaveListOfBoxes(f,lb);
01997 
01998   fclose(f);
01999 
02000   remove(fname);
02001   rename(tmpName,fname);
02002   free(tmpName);
02003 }
02004 
02005 void LoadCSState(char *fname,Tlist *lb,TCuikSystem *cs)
02006 {
02007   FILE *f;
02008   double tm;
02009   Titerator it;
02010   
02011   f=fopen(fname,"rb");
02012   if (!f)
02013     Error("Could not open file for loading CSState");
02014 
02015   fread(&tm,sizeof(double),1,f);
02016   LoadStatistics(f,&(cs->st));
02017   LoadListOfBoxes(f,lb);
02018 
02019   fclose(f);
02020   
02021   InitIterator(&it,lb);
02022   First(&it);
02023   if (cs->nvariables!=GetBoxNIntervals((Tbox *)GetCurrent(&it)))
02024     Error("The saved .state and the problem dimensionality do not match");
02025 
02026   /*Pretend that the process was started tm seconds before now*/
02027   SetInitialTime(GetTime(&(cs->st))-tm,&(cs->st));
02028 }
02029 
02030 
02031 /************************************************************************/
02032 /************************************************************************/
02033 /************************************************************************/
02034 
02035 /*
02036   Warms up the cuiksystem structure
02037 */
02038 void InitCuikSystem(TCuikSystem *cs)
02039 {
02040   InitVariables(&(cs->orig_variables));
02041   InitEquations(&(cs->orig_equations));
02042 
02043   /* cs->variables and cs->equations are initialized
02044      via Copy when simplifying the system*/ 
02045   cs->empty=TRUE;
02046 
02047   cs->updated=FALSE;
02048 
02049   cs->nequations=0;
02050   cs->nvariables=0;
02051 
02052   cs->systemVar=NULL;
02053   cs->notDummyVar=NULL;
02054   cs->varType=NULL;
02055 
02056   cs->orig2sd=NULL;
02057 
02058   cs->orig_nequations=0;
02059   cs->orig_nvariables=0;
02060 
02061   cs->orig_systemVar=NULL;
02062   cs->orig_notDummyVar=NULL;
02063 
02064   cs->searchMode=DEPTH_FIRST_SEARCH;
02065   InitEquation(&(cs->orig_eqMin));
02066 }
02067 
02068 /*
02069   Copies one cuiksystem structure into another (that is assumed as
02070   initialized but empty).
02071 */
02072 void CopyCuikSystem(TCuikSystem *cs_dst,TCuikSystem *cs_src)
02073 {
02074   cs_dst->empty=cs_src->empty; 
02075 
02076   CopyEquations(&(cs_dst->orig_equations),&(cs_src->orig_equations));
02077   CopyVariables(&(cs_dst->orig_variables),&(cs_src->orig_variables));
02078 
02079   CopyStatistics(&(cs_dst->st),&(cs_src->st));
02080 
02081   cs_dst->searchMode=cs_src->searchMode;
02082   CopyEquation(&(cs_dst->orig_eqMin),&(cs_src->orig_eqMin));
02083 
02084   cs_dst->updated=cs_src->updated; 
02085   if (cs_dst->updated)
02086     {
02087       CopyEquations(&(cs_dst->equations),&(cs_src->equations));
02088       CopyVariables(&(cs_dst->variables),&(cs_src->variables));
02089 
02090       NEW(cs_dst->orig2sd,1,Tmapping);
02091       CopyMapping(cs_dst->orig2sd,cs_src->orig2sd);
02092 
02093       cs_dst->nequations=cs_src->nequations;
02094       cs_dst->nvariables=cs_src->nvariables;
02095       if (cs_dst->nvariables==0)
02096         {
02097           cs_dst->systemVar=NULL;
02098           cs_dst->notDummyVar=NULL;
02099           cs_dst->varType=NULL;
02100         }
02101       else
02102         {
02103           NEW(cs_dst->systemVar,cs_dst->nvariables,boolean);
02104           memcpy(cs_dst->systemVar,cs_src->systemVar,sizeof(boolean)*cs_dst->nvariables);
02105           
02106           NEW(cs_dst->notDummyVar,cs_dst->nvariables,boolean);
02107           memcpy(cs_dst->notDummyVar,cs_src->notDummyVar,sizeof(boolean)*cs_dst->nvariables);
02108           
02109           NEW(cs_dst->varType,cs_dst->nvariables,unsigned int);
02110           memcpy(cs_dst->varType,cs_src->varType,sizeof(unsigned int)*cs_dst->nvariables);
02111         }
02112 
02113       cs_dst->orig_nequations=cs_src->orig_nequations;
02114       cs_dst->orig_nvariables=cs_src->orig_nvariables;
02115       if (cs_dst->orig_nvariables==0)
02116         {
02117           cs_dst->orig_systemVar=NULL;
02118           cs_dst->orig_notDummyVar=NULL;
02119         }
02120       else
02121         {
02122           NEW(cs_dst->orig_systemVar,cs_dst->orig_nvariables,boolean);
02123           memcpy(cs_dst->orig_systemVar,cs_src->orig_systemVar,sizeof(boolean)*cs_dst->orig_nvariables);
02124 
02125           NEW(cs_dst->orig_notDummyVar,cs_dst->orig_nvariables,boolean);
02126           memcpy(cs_dst->orig_notDummyVar,cs_src->orig_notDummyVar,sizeof(boolean)*cs_dst->orig_nvariables);
02127         }
02128         
02129       if (cs_dst->searchMode==MINIMIZATION_SEARCH)
02130         CopyEquation(&(cs_dst->eqMin),&(cs_src->eqMin));
02131     }
02132   else
02133     {
02134       cs_dst->orig2sd=NULL;
02135 
02136       cs_dst->nequations=0;
02137       cs_dst->nvariables=0;
02138       cs_dst->systemVar=NULL;  
02139       cs_dst->notDummyVar=NULL;
02140       cs_dst->varType=NULL;
02141 
02142       cs_dst->orig_nequations=0;
02143       cs_dst->orig_nvariables=0;
02144       cs_dst->orig_systemVar=NULL;  
02145       cs_dst->orig_notDummyVar=NULL;
02146     }
02147 }
02148 
02149 void CuikSystemMerge(Tparameters *p,TCuikSystem *cs1,TCuikSystem *cs2,TCuikSystem *cs)
02150 {
02151   unsigned int neq2,nvar1,nvar2;
02152   unsigned int i;
02153 
02154   InitCuikSystem(cs);
02155 
02156   cs->empty=((cs1->empty)&&(cs2->empty)); 
02157 
02158   cs->updated=FALSE; 
02159 
02160   cs->orig2sd=NULL;
02161   
02162   cs->nequations=0;
02163   cs->nvariables=0;
02164   cs->systemVar=NULL;  
02165   cs->notDummyVar=NULL;
02166   cs->varType=NULL;
02167   
02168   cs->orig_nequations=0;
02169   cs->orig_nvariables=0;
02170   cs->orig_systemVar=NULL;  
02171   cs->orig_notDummyVar=NULL;
02172 
02173   /* One of the sets of variables is supposed to be a sub-set of the
02174      other.
02175      If nvar1 is larger than the larger set was in cs1 and nothing has
02176      to be done*/
02177   CopyVariables(&(cs->orig_variables),&(cs1->orig_variables));
02178   nvar1=NVariables(&(cs1->orig_variables));
02179   nvar2=NVariables(&(cs2->orig_variables));
02180   for(i=nvar1;i<nvar2;i++)
02181     AddVariable2CS(GetVariable(i,&(cs2->orig_variables)),cs);
02182 
02183   CopyEquations(&(cs->orig_equations),&(cs1->orig_equations));
02184   neq2=NEquations(&(cs2->orig_equations));
02185   for(i=0;i<neq2;i++)
02186     AddEquation2CS(p,GetEquation(i,&(cs2->orig_equations)),cs);
02187 
02188   cs->searchMode=cs1->searchMode;
02189   CopyEquation(&(cs->orig_eqMin),&(cs1->orig_eqMin));
02190   AccumulateEquations(&(cs2->orig_eqMin),1,&(cs->orig_eqMin));
02191 }
02192 
02193 double EvaluateEqMin(void *b,void *cs)
02194 {
02195   double v=0;
02196 
02197   if (!((TCuikSystem *)cs)->updated)
02198     Error("The CuikSystem must be updated before using EvaluateEqMin");
02199 
02200   if (((TCuikSystem *)cs)->searchMode==MINIMIZATION_SEARCH)
02201     {      
02202       #if (0)
02203         double ct;
02204         unsigned int nv;
02205         double *p;
02206         unsigned int i;
02207         
02208         nv=NVariables(&(((TCuikSystem *)cs)->variables));
02209         
02210         ct=GetEquationValue(&(((TCuikSystem *)cs)->eqMin));
02211         
02212         NEW(p,nv,double);
02213         
02214         for(i=0;i<nv;i++)
02215           p[i]=IntervalCenter(GetBoxInterval(i,(Tbox *)b));
02216 
02217         v=EvaluateEquation(p,&(((TCuikSystem *)cs)->eqMin))-ct; 
02218 
02219         free(p);
02220       #else
02221         Tinterval ie;
02222         double ct;
02223 
02224         ct=GetEquationValue(&(((TCuikSystem *)cs)->eqMin));
02225         
02226         EvaluateEquationInt(GetBoxIntervals((Tbox *)b),&ie,&(((TCuikSystem *)cs)->eqMin));
02227         IntervalOffset(&ie,-ct,&ie);
02228 
02229         /*v=LowerLimit(&ie);*/
02230         /*v=UpperLimit(&ie);*/
02231         v=IntervalCenter(&ie);
02232       #endif
02233     }
02234   return(v);
02235 }
02236 
02237 boolean CmpBoxesEquation(void *b1,void *b2,void *cs)
02238 {
02239   return(EvaluateEqMin(b1,cs)<EvaluateEqMin(b2,cs));
02240 }
02241 
02242 void SetCSSearchMode(unsigned int sm,Tequation *eqMin,TCuikSystem *cs)
02243 {
02244   switch(sm)
02245     {
02246     case DEPTH_FIRST_SEARCH:
02247       cs->searchMode=DEPTH_FIRST_SEARCH;
02248       break;
02249     case BREADTH_FIRST_SEARCH:
02250       cs->searchMode=BREADTH_FIRST_SEARCH;
02251       break;
02252     case MINIMIZATION_SEARCH:
02253       cs->searchMode=MINIMIZATION_SEARCH;
02254       DeleteEquation(&(cs->orig_eqMin));
02255       CopyEquation(&(cs->orig_eqMin),eqMin);
02256       break;
02257     default:
02258       Error("Unkonwn search mode in SetCSSearchMode");
02259     }
02260 }
02261 
02262 void AddTerm2SearchCriterion(double w,unsigned int v,double val,TCuikSystem *cs)
02263 {
02264   if (w!=0.0)
02265     {
02266       Tequation eq;
02267       Tmonomial m;
02268       
02269       InitEquation(&eq);
02270       SetEquationCmp(EQU,&eq);
02271       InitMonomial(&m);
02272       
02273       AddCt2Monomial(w,&m);
02274       AddVariable2Monomial(v,2,&m);
02275       AddMonomial(&m,&eq);
02276       ResetMonomial(&m);
02277       
02278       AddCt2Monomial(-w*2*val,&m);
02279       AddVariable2Monomial(v,1,&m);
02280       AddMonomial(&m,&eq);
02281       ResetMonomial(&m);
02282       
02283       AddCt2Monomial(w*val*val,&m);
02284       AddMonomial(&m,&eq);
02285       ResetMonomial(&m);
02286       
02287       if (cs->searchMode==MINIMIZATION_SEARCH)
02288         AccumulateEquations(&eq,1,&(cs->orig_eqMin));
02289       else
02290         SetCSSearchMode(MINIMIZATION_SEARCH,&eq,cs);
02291       
02292       DeleteMonomial(&m);
02293       DeleteEquation(&eq);
02294     }
02295 }
02296 
02297 /*
02298   Adds a equation to the CuikSystem. 
02299   Equations as added by the user are not dummified. This helps
02300   when simplifying the system (dummify variables can prevent some
02301   simplifications or make them more "obscure")
02302   The dummificitaion is applied after the simplification of the
02303   system (see SimplifyCuikSystem)
02304 */
02305 void AddEquation2CS(Tparameters *p,Tequation *eq,TCuikSystem *cs)
02306 {
02307   if (cs->updated)
02308     UnUpdateCuikSystem(cs);
02309 
02310   if (eq!=NULL)
02311     AddEquation(eq,&(cs->orig_equations));
02312 }
02313 
02314 /*
02315   Checks if the system has a variable with the given name.
02316   If so, we return the variable identifier.
02317   If not, we create a new variable
02318  */
02319 unsigned int AddVariable2CS(Tvariable *v,TCuikSystem *cs)
02320 {
02321   unsigned int id;
02322 
02323   if (cs->updated)
02324     UnUpdateCuikSystem(cs);
02325 
02326   id=GetVariableID(GetVariableName(v),&(cs->orig_variables));
02327 
02328   if (id==NO_UINT)
02329     id=AddVariable(v,&(cs->orig_variables));
02330 
02331   return(id);
02332 }
02333 
02334 /*
02335   Returns a copy of the variables stored in the CuikSystem
02336 */
02337 void GetCSVariables(Tvariables *vs,TCuikSystem *cs)
02338 {
02339   CopyVariables(vs,&(cs->orig_variables));
02340 }
02341 
02342 /*
02343   Returns the number of variables in the CuikSystem
02344 */
02345 unsigned int GetCSNumVariables(TCuikSystem *cs)
02346 {
02347   return(NVariables(&(cs->orig_variables)));
02348 }
02349 
02350 /*
02351   Returns the number of system variables in the CuikSystem
02352 */
02353 unsigned int GetCSNumNonDummyVariables(TCuikSystem *cs)
02354 {
02355   return(NVariables(&(cs->orig_variables))-GetNumDummyVariables(&(cs->orig_variables)));
02356 }
02357 
02358 /* 
02359    Gets a copy of variable with ID 'n'
02360 */
02361 void GetCSVariable(unsigned int n,Tvariable *v,TCuikSystem *cs)
02362 {
02363   CopyVariable(v,GetVariable(n,&(cs->orig_variables)));
02364 }
02365 
02366 /*
02367   Sets a new range for variable with ID 'n'
02368 */
02369 void SetCSVariableRange(unsigned int n,Tinterval *r,TCuikSystem *cs)
02370 { 
02371   if (cs->updated)
02372     UnUpdateCuikSystem(cs); /* Variables with ct range are simplified in
02373                                the UpdateCuikSystem */
02374 
02375   SetVariableInterval(r,GetVariable(n,&(cs->orig_variables)));
02376 }
02377 
02378 /*
02379   Gets the ID of the variable with the given name
02380 */
02381 unsigned int GetCSVariableID(char *name,TCuikSystem *cs)
02382 {
02383   return(GetVariableID(name,&(cs->orig_variables)));
02384 }
02385 
02386 /*
02387   Returns an array of booleans with sv[i]=TRUE if variable
02388   'i' is a system variable.
02389   Also returns the number of variables in the CuikSystem
02390 */
02391 unsigned int GetCSSystemVars(boolean **sv,TCuikSystem *cs)
02392 {
02393   unsigned int i,n;
02394 
02395   n=NVariables(&(cs->orig_variables));
02396   NEW(*sv,n,boolean);
02397 
02398   for(i=0;i<n;i++)
02399     (*sv)[i]=((IsSystemVariable(i,&(cs->orig_variables)))||
02400               (IsSecondaryVariable(i,&(cs->orig_variables))));
02401   return(n);
02402 }
02403 
02404 /*
02405   Returns a copy of the equations in the cuiksystem
02406 */
02407 void GetCSEquations(Tequations *eqs,TCuikSystem *cs)
02408 {
02409   CopyEquations(eqs,&(cs->orig_equations));
02410 }
02411 
02412 /*
02413   Returns a copy of equation 'n' in the CuikSystem
02414 */
02415 void GetCSEquation(unsigned int n,Tequation *eq,TCuikSystem *cs)
02416 {
02417   CopyEquation(eq,GetEquation(n,&(cs->orig_equations)));
02418 }
02419 
02420 /*
02421   Returns the number of equations in the CuikSytem
02422 */
02423 unsigned int GetCSNumEquations(TCuikSystem *cs)
02424 {
02425   return(NEquations(&(cs->orig_equations)));
02426 }
02427 
02428 void GetCuikSystemJacobian(Tequation ***J,TCuikSystem *cs)
02429 {
02430   unsigned int i,j,neqs,nvars;
02431 
02432   neqs=NEquations(&(cs->orig_equations));
02433   nvars=NVariables(&(cs->orig_variables));
02434 
02435   NEW((*J),neqs,Tequation *);
02436   for(i=0;i<neqs;i++)
02437     {
02438       NEW((*J)[i],nvars,Tequation);
02439       for(j=0;j<nvars;j++)
02440         DeriveEquation(j,&((*J)[i][j]),GetEquation(i,&(cs->orig_equations)));
02441     }
02442 }
02443 
02444 void DeleteCuikSystemJacobian(Tequation **J,TCuikSystem *cs)
02445 {
02446   unsigned int i,j,neqs,nvars;
02447   
02448   neqs=NEquations(&(cs->orig_equations));
02449   nvars=NVariables(&(cs->orig_variables));
02450 
02451   for(i=0;i<neqs;i++)
02452     {
02453       for(j=0;j<nvars;j++)
02454         DeleteEquation(&(J[i][j]));
02455       free(J[i]);
02456     }
02457   free(J);
02458 }
02459 
02460 
02461 void ComputeSimpCuikSystemJacobian(TCuikSystem *cs)
02462 {
02463   unsigned int i,j,k;
02464   Tequation *eq;
02465 
02466   NEW(cs->J,cs->simp_nee,Tequation *);
02467   k=0;
02468   for(i=0;i<cs->simp_nee;i++)
02469     {
02470       eq=GetEquation(i,&(cs->simp_equations));
02471       if (GetEquationCmp(eq)==EQU)
02472         {
02473           NEW(cs->J[k],cs->simp_nvariables,Tequation);
02474           for(j=0;j<cs->simp_nvariables;j++)
02475             DeriveEquation(j,&(cs->J[k][j]),eq);
02476           k++;
02477         }
02478     }
02479 }
02480 
02481 void DeleteSimpCuikSystemJacobian(TCuikSystem *cs)
02482 {
02483   unsigned int i,j;
02484   
02485   if (!cs->updated)
02486     Error("DeleteSimpCuikSystemJacobian can only be used on updated cuiksystems");
02487 
02488   for(i=0;i<cs->simp_nee;i++)
02489     {
02490       for(j=0;j<cs->simp_nvariables;j++)
02491         DeleteEquation(&(cs->J[i][j]));
02492       free(cs->J[i]);
02493     }
02494   free(cs->J);
02495 }
02496 
02497 /*
02498   Reduces a box as much as possible (according to parameters in 'p').
02499   If the set of parameters is undefined, we use a default set.
02500   This procedure is used in CuikPlan.
02501   
02502   This is basically another flavor of ReduceBox where parameters
02503   are given in one structure instead of as different inputs
02504 
02505   The input box and output boxes are refered to the original
02506   cuiksystem (the non-simplified one)
02507   
02508   The output can be EMPTY_BOX
02509                     REDUCED_BOX
02510                     REDUCED_BOX_WITH_SOLUTION
02511                     ERROR_IN_PROCESS
02512   
02513 */
02514 unsigned int MaxReduction(Tparameters *p,unsigned int varMask,Tbox *b,TCuikSystem *cs)
02515 {
02516   unsigned int e;
02517   
02518   if (UpdateCuikSystem(p,cs))
02519     {
02520       Tbox bsimp;
02521       
02522       SimpleFromOriginal(b,&bsimp,cs->orig2sd);
02523       e=ReduceBox(p,(varMask==0?~DUMMY_VAR:varMask),&bsimp,cs);
02524       if (e!=EMPTY_BOX)
02525         {
02526           /* ERROR_IN_PROCESS, REDUCED_BOX, REDUCED_BOX_WITH_SOLUTION*/
02527           UpdateOriginalFromSimple(&bsimp,b,cs->orig2sd);
02528         }
02529       DeleteBox(&bsimp);
02530     }
02531   else
02532     e=EMPTY_BOX;
02533 
02534   return(e);
02535 }
02536 
02537 
02538 boolean SampleCuikSystem(Tparameters *p,char *fname,Tlist *sb,
02539                          unsigned int nsamples,unsigned int ntries,
02540                          unsigned int ndof,TCuikSystem *cs)
02541 {
02542   Tbox init_box;
02543   boolean haveSample;
02544 
02545   GenerateInitialBox(&init_box,cs);
02546 
02547   haveSample=SampleCuikSystemInBox(p,fname,sb,nsamples,ntries,ndof,&init_box,cs);
02548   
02549   DeleteBox(&init_box);
02550   
02551   return(haveSample);
02552 }
02553 
02554 boolean SampleCuikSystemInBox(Tparameters *p,char *fname,Tlist *sb,
02555                               unsigned int nsamples,unsigned int ntries,
02556                               unsigned int ndof,
02557                               Tbox *init_box,TCuikSystem *cs)
02558 {
02559   Tbox orig_ranges,b,*bAux,*box;
02560   Tlist solutions;
02561   unsigned int k,d,ns,nv,ne,i,nt;
02562   double v;
02563       
02564   Tfilename fsols_box;
02565   Tfilename fsols_point;
02566 
02567   FILE *f_out_box;  
02568   FILE *f_out_point;  
02569 
02570   Titerator it;
02571   boolean *systemVars;
02572   Tinterval *r;
02573   unsigned int spt;
02574   double ms;
02575 
02576   boolean ok;
02577   boolean end;
02578 
02579   /* free var = variable not in equations -> must be fixed always */
02580   unsigned int *freeVars;
02581   unsigned int nFreeVars;
02582 
02583   /*Get a copy of the ranges in 'cs' for all the variables*/
02584   GenerateInitialBox(&orig_ranges,cs);
02585   
02586   /*Set the ranges for the 'cs' variables to those in the given box (init_box)*/
02587   if (cs->updated) 
02588     UnUpdateCuikSystem(cs);
02589 
02590   nv=NVariables(&(cs->orig_variables));
02591   for(k=0;k<nv;k++)
02592     SetVariableInterval(GetBoxInterval(k,init_box),GetVariable(k,&(cs->orig_variables)));
02593 
02594   NEW(freeVars,nv,unsigned int);
02595   nFreeVars=0;
02596   for(k=0;k<nv;k++)
02597     {
02598       if ((GetVariableTypeN(k,&(cs->orig_variables))==SYSTEM_VAR)&&
02599           (!UsedVarInEquations(k,&(cs->orig_equations))))
02600         {
02601           freeVars[nFreeVars]=k;
02602           nFreeVars++;
02603         }
02604     }
02605 
02606   /*Change the SPLIT_TYPE parameter to random split*/
02607   spt=(unsigned int)GetParameter(CT_SPLIT_TYPE,p);
02608   ChangeParameter(CT_SPLIT_TYPE,2,p); /* select split dimentions at random */
02609   /*Change the SMALL_SIGMA paramter to ensure it is small enough.
02610     SMALL_SIGMA controls the precission of the isolated solutions and, thus, of the
02611     sampled points. */
02612   ms=GetParameter(CT_SMALL_SIGMA,p);
02613   ChangeParameter(CT_SMALL_SIGMA,100*GetParameter(CT_EPSILON,p),p);
02614 
02615   if (fname==NULL)
02616     {
02617       f_out_box=NULL;
02618       f_out_point=NULL;
02619     }
02620   else
02621     {
02622       /* Check if we can create the output files */
02623       CreateFileName(NULL,fname,"_samples",SOL_EXT,&fsols_box);
02624       f_out_box=fopen(GetFileFullName(&fsols_box),"w"); 
02625       if (!f_out_box)
02626         Error("Could not open box sample output file");
02627       
02628       CreateFileName(NULL,fname,NULL,SAMPLE_EXT,&fsols_point);
02629       f_out_point=fopen(GetFileFullName(&fsols_point),"w"); 
02630       if (!f_out_point)
02631         Error("Could not open box sample output file");
02632     }
02633 
02634   if (sb!=NULL)
02635     InitListOfBoxes(sb);
02636 
02637   nv=GetCSNumVariables(cs);
02638   ne=GetCSNumEquations(cs);
02639 
02640   if (ndof==NO_UINT)
02641     {
02642       /* try to get the number of dof from the system (vars-equations) */
02643       if (ne>=nv)
02644         Error("Over/Well-constrained system. Please indicate the number of dof in the call");
02645       ndof=nv-ne;
02646     }
02647 
02648   if (MaxReduction(p,~DUMMY_VAR,init_box,cs)==EMPTY_BOX)
02649     end=TRUE;
02650   else
02651     end=FALSE;
02652 
02653   if (nFreeVars>ndof)
02654     Error("More free vars than degrees of freedom");
02655 
02656   ns=0; /*samples already determined*/
02657   nt=0;
02658   while((!end)&&(ns<nsamples))
02659     {
02660       do {
02661         ok=TRUE;
02662 
02663         /*fix 'ndof' varibles*/
02664         CopyBox(&b,init_box);
02665         for(k=0;k<nv;k++)
02666           SetCSVariableRange(k,GetBoxInterval(k,&b),cs);
02667         
02668         for(k=0;k<nFreeVars;k++)
02669           {     
02670             r=GetBoxInterval(freeVars[k],&b);
02671             v=randomInInterval(r);
02672             
02673             #if (_DEBUG>1)
02674               printf("[CS]->fixing %u to %f\n",freeVars[k],v);
02675             #endif
02676             
02677             NewInterval(v,v,r);
02678             
02679             SetCSVariableRange(freeVars[k],r,cs);
02680           }
02681 
02682         for(k=nFreeVars;((ok)&&(k<ndof));k++)
02683           {
02684             /*fix 'ndof' varibles*/
02685             d=ComputeSplitDim(p,&b,cs);
02686 
02687             if (d==NO_UINT)
02688               ok=FALSE;
02689             else
02690               {
02691                 r=GetBoxInterval(d,&b);
02692                 v=randomInInterval(r);
02693                 
02694                 #if (_DEBUG>1)
02695                   printf("[CS]->fixing %u to %f\n",d,v);
02696                 #endif
02697 
02698                 NewInterval(v,v,r);
02699                 
02700                 SetCSVariableRange(d,r,cs);
02701               }
02702           }
02703         if (ok)
02704           {           
02705             #if (_DEBUG>1)
02706               printf("[CS]");PrintBox(stdout,&b);
02707             #endif
02708           }
02709         else
02710           {
02711             #if (_DEBUG>1)
02712               printf("Inconsistent system while sampling\n");
02713             #endif
02714           }
02715       
02716         DeleteBox(&b);
02717      
02718         nt++;
02719         if ((ntries!=NO_UINT)&&(nt==ntries))
02720           end=TRUE;
02721       } while((!ok)&&(!end));
02722 
02723       if (!end)
02724         {
02725           
02726           InitListOfBoxes(&solutions);
02727 
02728           /*See if there are solutions for the fixed ranges*/
02729           SolveCuikSystem(p,nsamples-ns,FALSE,NULL,f_out_box,&solutions,cs);
02730           
02731           /*We have to print the samples*/
02732           GetCSSystemVars(&systemVars,cs);
02733           InitIterator(&it,&solutions);
02734           First(&it);
02735           while((!EndOfList(&it))&&(ns<nsamples))
02736             {
02737               bAux=(Tbox *)GetCurrent(&it);
02738 
02739               if (f_out_point!=NULL)
02740                 {
02741                   /* Print the center of the box into the point file */
02742                   /* We only print values for the system vars */
02743                   for(i=0;i<nv;i++)
02744                     {
02745                       if (systemVars[i])
02746                         fprintf(f_out_point," %.12g",IntervalCenter(GetBoxInterval(i,bAux)));
02747                     }
02748                   fprintf(f_out_point,"\n");
02749                 }
02750               if (sb!=NULL)
02751                 {
02752                   NEW(box,1,Tbox); 
02753             
02754                   CopyBox(box,bAux);
02755             
02756                   AddLastElement((void *)box,sb);
02757                 }
02758         
02759               ns++;
02760               Advance(&it);
02761             }
02762           free(systemVars);
02763 
02764           fflush(f_out_point);
02765           fflush(f_out_box);
02766 
02767           /*Remove all boxes from the list and the current box*/
02768           DeleteListOfBoxes(&solutions);
02769         }
02770     } 
02771 
02772   if (f_out_box!=NULL)
02773     {
02774       DeleteFileName(&fsols_box);
02775       fclose(f_out_box);
02776     }
02777   if (f_out_point!=NULL)
02778     {
02779       fclose(f_out_point);
02780       DeleteFileName(&fsols_point);
02781     }
02782 
02783   /*Restore the user given split_type and min_sigma*/
02784   ChangeParameter(CT_SPLIT_TYPE,spt,p);
02785   ChangeParameter(CT_SMALL_SIGMA,ms,p);
02786 
02787   /*Return the original ranges to the 'cs' variables*/
02788   if (cs->updated) 
02789     UnUpdateCuikSystem(cs);
02790 
02791   nv=NVariables(&(cs->orig_variables));
02792   for(k=0;k<nv;k++)
02793     SetVariableInterval(GetBoxInterval(k,&orig_ranges),GetVariable(k,&(cs->orig_variables)));
02794 
02795   free(freeVars);
02796 
02797   DeleteBox(&orig_ranges);
02798   
02799   return(!end);
02800 }
02801 
02802 /*
02803   Takes a cuik systema and returns all solutions. 
02804   Solutions are stored in file 'f_out' (if defined) and in list 'sol'
02805   (if defined), or both.
02806 
02807   This procedure is used for single-cpu versions of Cuik.
02808  */
02809 void SolveCuikSystem(Tparameters *p,unsigned int nsols,
02810                      boolean restart,char *fstate,
02811                      FILE *f_out,Tlist *sol,TCuikSystem *cs)
02812 {
02813   Theap boxes;
02814   #if (_DEBUG>0)
02815     double box_volume;
02816   #endif
02817   #if (_DEBUG>1)
02818     unsigned int nbox=0;
02819   #endif 
02820 
02821   Tbox b;
02822   unsigned int c; /* output of ReduceBox */
02823   unsigned int current_level; /* level of the current box in the search three */
02824   Tbox init_box;
02825   boolean done;
02826   unsigned int nb; /*boxes for recovery mode*/
02827   unsigned int statePeriod;
02828 
02829   /************************************************************************************/
02830   /************************************************************************************/
02831   /************************************************************************************/
02832 
02833   if (UpdateCuikSystem(p,cs))
02834     {
02835       
02836       switch(cs->searchMode)
02837         {
02838         case DEPTH_FIRST_SEARCH:
02839           InitHeapOfBoxes(CmpBoxDepthFirst,NULL,&boxes);
02840           break;
02841         case BREADTH_FIRST_SEARCH:
02842           InitHeapOfBoxes(CmpBoxBreadthFirst,NULL,&boxes);
02843           break;
02844         case MINIMIZATION_SEARCH:
02845           InitHeapOfBoxes(CmpBoxesEquation,(void *)cs,&boxes);
02846           break;
02847         }
02848 
02849       if ((restart)&&(fstate!=NULL))
02850         {
02851           Tlist pboxes;
02852 
02853           LoadCSState(fstate,&pboxes,cs);
02854           AddList2Heap(&pboxes,&boxes);
02855           DeleteListOfBoxes(&pboxes);
02856         }
02857       else
02858         {
02859           BoxFromVariables(&init_box,&(cs->variables));      
02860           AddBox2HeapOfBoxes(&init_box,&boxes);
02861           DeleteBox(&init_box);
02862 
02863           InitStatistics(1,HeapOfBoxesVolume(cs->systemVar,&boxes),&(cs->st));
02864         }
02865 
02866       current_level=0;
02867       nb=0;
02868       statePeriod=GetParameter(CT_STATE_PERIOD,p);
02869 
02870       done=FALSE;
02871 
02872       /*the cuik solve process itself*/
02873       do {
02874         if(!HeapEmpty(&boxes))
02875           {
02876             /*Get a new box*/
02877 
02878             if ((statePeriod>0)&&(fstate!=NULL))
02879               {
02880                 nb++;
02881                 if (nb==statePeriod)
02882                   {
02883                     Tlist pboxes;
02884 
02885                     Heap2List(&pboxes,&boxes);
02886                     SaveCSState(fstate,&pboxes,cs);
02887                     DeleteListOfBoxes(&pboxes);
02888                     nb=0;
02889                   }
02890               }
02891 
02892             NewBoxProcessed(&(cs->st));
02893 
02894             /*The box is extracted to avoid another process 
02895               to get the same box*/
02896             ExtractMinElement(&b,&boxes); 
02897 
02898             current_level=GetBoxLevel(&b);
02899 
02900             NewMaxLevel(current_level,&(cs->st));
02901 
02902             #if (_DEBUG>0)
02903               fprintf(stderr,"<%g %g>[%u]",
02904                       GetBoxVolume(cs->systemVar,&b),
02905                       GetBoxSize(cs->systemVar,&b),
02906                       current_level);
02907               box_volume=GetBoxVolume(cs->systemVar,&b);
02908             #endif
02909 
02910             #if (_DEBUG>1)
02911               printf("\n\n%u: Analizing box: ",nbox);
02912               nbox++;
02913               PrintBox(stdout,&b);
02914               printf("      Box level   : %u\n",GetBoxLevel(&b));
02915               printf("      Box volume  : %g\n",GetBoxVolume(cs->systemVar,&b));
02916               printf("      Box size    : %g\n",GetBoxSize(cs->systemVar,&b));
02917               if (cs->searchMode==MINIMIZATION_SEARCH)
02918                 printf("      Box penalty : %g\n",EvaluateEqMin((void *)&b,(void *)cs));
02919             #endif
02920 
02921             /* Reduce the box by all but dummy vars */;
02922             c=ReduceBox(p,~DUMMY_VAR,&b,cs);
02923         
02924             #if (_DEBUG>0)
02925               fprintf(stderr,"  -> ");
02926             #endif  
02927 
02928             PostProcessBox(p,c,f_out,sol,&boxes,&b,cs);
02929 
02930             if (nsols>0)
02931               done=(GetNSolutionBoxes(&(cs->st))==nsols);
02932 
02933             DeleteBox(&b);
02934           }
02935       } while((!done)&&(!HeapEmpty(&boxes))); /*Until everything is completed*/
02936 
02937       DeleteHeap(&boxes); /*for sanity we delete the empty list*/
02938 
02939       PrintStatistics((f_out==NULL?stdout:f_out),&(cs->st));
02940     }
02941 }
02942 
02943 
02944 #if (_USE_MPI)
02945 /*
02946   In multi-cpu versions we use a MPI version of CuikSolve.
02947   One of the CPUs takes the role of scheduler in charge of managing the
02948   lists of boxes pending to be processed and classifing boxes out of
02949   reduction process as solutions of boxes to be split.
02950   The rest of CPUs take the charge of reducing boxes (i.e., of executing
02951   ReduceBox to the boxes received from the scheduler) and of returning
02952   the resulting boxes (with the associated result code) to the
02953   scheduler.
02954 
02955   The scheduler has to take into account that some child nodes can
02956   'die' while reducing boxes. So it has to keep track of when a box was
02957   sent to a child and prediodically check whether a timeout was been reached.
02958   If so, the corresponding processor is considered as 'dead' the
02959   box sent is recovered and added to the list of boxes to be processed
02960   (i.e., send to other child nodes still alive).
02961 
02962   The scheduler should considere the extreme case where all child process die
02963   and should take care of "awakening" dead processors.
02964   This is not implemented.... till now.
02965 */
02966 void MPI_SolveCuikSystem(Tparameters *p,
02967                          boolean restart,char *fstate,
02968                          FILE *f_out,TCuikSystem *cs)
02969 {
02970   Theap boxes;  /*queued boxes*/
02971   Tbox b;
02972   unsigned int c;
02973   unsigned int nr;
02974   unsigned int current_level;
02975 
02976   /*Variables to set up the parallelism*/
02977   unsigned int in_process; /* number of boxes send to child processors and still
02978                               in process */
02979   unsigned int available; /* number of child processors available */
02980   signed int np; /* number of processors used (np-1) is the number of childs (process
02981                     0 is the scheduler) */
02982   MPI_Status status; /* Output status of a MPI command */
02983   MPI_Request *request; /* Communication request. When the scheduller sends out a box
02984                            is starts a communication request */
02985   unsigned int buffer_size; /* Size of a buffer of doubles where we store the 
02986                                information of a box */
02987   double **buffers_out; /* boxes send to the child processors */
02988   double **buffers_in;  /* boxes returned by the child processors */
02989   signed int i,completed; /* MPI_Testany returns completed=1 if any of the pending 
02990                              communications requests has been replied (then, 'i' 
02991                              is the number of the compleated request)*/
02992   boolean *lost_packet; /* true if a box was never returned */
02993   time_t *time_stamp; /* time when we send out a box */
02994   time_t deadline; /* deadline (in seconds) used to compute the maximum expected
02995                       return time for a box*/
02996   Tbox init_box;  /* initial search space */
02997   unsigned int nb;
02998   unsigned int statePeriod;
02999 
03000   /*lowest possible priority but not as low as that of the children processors*/
03001   /*setpriority(PRIO_PROCESS,0,PRIO_MAX-1); */
03002 
03003   MPI_Comm_size(MPI_COMM_WORLD,&np); /*total number of processes (take into 
03004                                        account that this routine is process number 0)*/
03005   
03006   if (UpdateCuikSystem(p,cs))
03007     {
03008       switch(cs->searchMode)
03009         {
03010         case DEPTH_FIRST_SEARCH:
03011           InitHeapOfBoxes(CmpBoxDepthFirst,NULL,&boxes);
03012           break;
03013         case BREADTH_FIRST_SEARCH:
03014           InitHeapOfBoxes(CmpBoxBreadthFirst,NULL,&boxes);
03015           break;
03016         case MINIMIZATION_SEARCH:
03017           InitHeapOfBoxes(CmpBoxesEquation,(void *)cs,&boxes);
03018           break;
03019         }
03020 
03021       BoxFromVariables(&init_box,&(cs->variables));
03022       
03023       /* Reserve space for the boxes sent/received and associated information */
03024       /*All boxes are the same size as the initial one*/        
03025       buffer_size=GetBoxBufferSize(&init_box);
03026 
03027       if ((restart)&&(fstate!=NULL))
03028         {
03029           Tlist pboxes;
03030 
03031           LoadCSState(fstate,&pboxes,cs);
03032           AddList2Heap(&pboxes,&boxes);
03033           DeleteListOfBoxes(&pboxes);
03034         }
03035       else
03036         {
03037           AddBox2HeapOfBoxes(&init_box,&boxes);
03038           InitStatistics(np,HeapOfBoxesVolume(cs->systemVar,&boxes),&(cs->st));
03039         }
03040       DeleteBox(&init_box);
03041 
03042       current_level=0;
03043 
03044       NEW(buffers_out,np,double*);
03045       NEW(buffers_in,np,double*);
03046     
03047       NEW(request,np,MPI_Request);
03048       NEW(lost_packet,np,boolean);
03049       NEW(time_stamp,np,time_t);
03050 
03051       for(i=1;i<np;i++)
03052         {
03053           request[i]=MPI_REQUEST_NULL;
03054           NEW(buffers_out[i],buffer_size,double);
03055           NEW(buffers_in[i],buffer_size,double);
03056           lost_packet[i]=FALSE;
03057         }
03058 
03059       request[0]=MPI_REQUEST_NULL; /* Processor 0 is the scheduler, do not use it as a child */
03060       in_process=0;
03061       available=(np-1);
03062         
03063       nb=0;
03064       statePeriod=GetParameter(CT_STATE_PERIOD,p);
03065 
03066       /*the cuik solve process itself*/
03067       do {
03068 
03069         if ((!HeapEmpty(&boxes))&& /* there is something to be processes */
03070             (available>0)) /* and someone ready to process it */
03071           {
03072             /* Search for a free child (at least one must exists) */
03073             i=1;
03074             while ((i<np)&&(request[i]!=MPI_REQUEST_NULL)) i++;
03075                   
03076             if (i==np)
03077               Error("wrong number of available processors");
03078             else
03079               {
03080                 if ((statePeriod>0)&&(fstate!=NULL))
03081                   {
03082                     nb++;
03083                     if (nb==statePeriod)
03084                       {
03085                         Tbox btmp;
03086                         unsigned int ctmp,ntmp;
03087                         Tlist pboxes;
03088                         unsigned int kk;
03089 
03090                         Heap2List(&pboxes,&boxes);
03091                         for(kk=1;kk<np;kk++)
03092                           {
03093                             if (request[kk]!=MPI_REQUEST_NULL)
03094                               { 
03095                                 InitBox(cs->nvariables,NULL,&btmp);
03096                                 Buffer2Box(&ctmp,&ntmp,buffers_out[kk],&btmp);
03097                                 AddFirstElement((void *)&btmp,&pboxes);
03098                               }
03099                           }
03100                         SaveCSState(fstate,&pboxes,cs);
03101                         DeleteListOfBoxes(&pboxes);
03102                         nb=0;
03103                       }
03104                   }
03105 
03106                 /*Get a new box*/
03107                 ExtractMinElement(&b,&boxes); 
03108             
03109                 /* Transform the box into a buffer of doubles */
03110                 Box2Buffer(REDUCED_BOX,0,buffers_out[i],&b);
03111             
03112                 /* Send it to the iddle child processors */
03113                 /* and start waiting for the reply (i.e., the reduced box) */
03114                 if (MPI_Send(buffers_out[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD)==MPI_SUCCESS)
03115                   {
03116                     /* The box is sent and now we start waiting for it */
03117                     if (MPI_Irecv(buffers_in[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD,&(request[i]))==MPI_SUCCESS)
03118                       {
03119 
03120                         current_level=GetBoxLevel(&b);
03121                         
03122                         NewBoxProcessed(&(cs->st));
03123                         NewMaxLevel(current_level,&(cs->st));
03124                         
03125                         /* One more box is in process */
03126                         in_process++;
03127                         
03128                         /* One less processor is available */
03129                         available--;
03130                         
03131                         #if (_DEBUG>0)
03132                           /* Inform about the box launchig */
03133                           fprintf(stderr,"b<v:%g, s:%g, l:%u>-> %u\n",
03134                                   GetBoxVolume(cs->systemVar,&b),
03135                                   GetBoxSize(cs->systemVar,&b),
03136                                   current_level,i);
03137                           /*
03138                           fprintf(stderr,"   A:%d   P:%d  Q:%u\n", 
03139                                   available,in_process,HeapSize(&boxes));
03140                           */
03141                         #endif  
03142                         
03143                         /* Store the time at which we sent out the box */
03144                         time_stamp[i]=time(NULL);
03145                         /* and, mark the sent box as not lost */
03146                         lost_packet[i]=FALSE;
03147                         
03148                         #if (_DEBUG>1)
03149                           printf("Sending box to processors : %u (iddle -> %u box_in_list-> %u)\n",
03150                                  i,np-in_process-1,HeapSize(&boxes));
03151                           printf("  Box: ");
03152                           PrintBox(stdout,&b);
03153                         #endif
03154                         
03155                         DeleteBox(&b);
03156                       }
03157                     else
03158                       {
03159                         /*The box will never be back: add it to the list and free the processor */
03160                         #if (_DEBUG>0)
03161                           fprintf(stderr,"RF-> %u\n",i);
03162                         #endif
03163                         
03164                         AddBox2HeapOfBoxes(&b,&boxes);
03165                         request[i]=MPI_REQUEST_NULL;
03166                       }
03167                   }
03168                 else
03169                   {
03170                     /* We didn't manage to send out the box, just return it to the boxes
03171                        to be processes*/ 
03172                     #if (_DEBUG>0)
03173                       fprintf(stderr,"SF-> %u\n",i);
03174                     #endif
03175 
03176                     AddBox2HeapOfBoxes(&b,&boxes);
03177                   }
03178               }
03179           }
03180 
03181         /* see if we already got any reply from the slaves :-) */
03182         if ((MPI_Testany(np,request,&i,&completed,&status)==MPI_SUCCESS)&&
03183             (completed))
03184           {
03185             /* if 'completed' 'i' is the request completed */
03186             #if (_DEBUG>1)
03187               printf("Receiving box from processors : %u\n",i);
03188             #endif
03189 
03190             available++; /* either if lost or not, the processor becomes available from now  on */
03191             request[i]=MPI_REQUEST_NULL; 
03192 
03193             if (!lost_packet[i])
03194               {
03195                 /* If so, reconstruct the output box and analyze it */
03196                 InitBox(cs->nvariables,NULL,&b);
03197 
03198                 Buffer2Box(&c,&nr,buffers_in[i],&b);
03199 
03200                 AddNBoxReductions(nr,&(cs->st));
03201 
03202                 in_process--; /* lost ones are already discounted when classified as lost 
03203                                  (to be able to finish even if lost ones exits)*/
03204 
03205                 #if (_DEBUG>0)
03206                   fprintf(stderr,"  %u->b<v:%g s:%g l:%u>(t=%lu): ",
03207                           i,
03208                           GetBoxVolume(cs->systemVar,&b),
03209                           GetBoxSize(cs->systemVar,&b),
03210                           GetBoxLevel(&b),
03211                           time(NULL)-time_stamp[i]);
03212                   /*
03213                     fprintf(stderr,"   A:%d   P:%d  Q:%u\n", 
03214                     available,in_process,HeapSize(&boxes)); 
03215                   */
03216                 #endif
03217 
03218                 PostProcessBox(p,c,f_out,NULL,&boxes,&b,cs);
03219 
03220                 DeleteBox(&b);
03221               }
03222             #if (_DEBUG>0)
03223             else
03224               {
03225                 /* We receive a box that was thought to be lost. The only think we
03226                    do is to mark the child as available again by setting request[i]=MPI_REQUEST_NULL;
03227                    below */
03228                 fprintf(stderr,"  lb[%u](t=%lu > %u)\n",i,
03229                         time(NULL)-time_stamp[i],MPI_TREAT_BOX_TIMEOUT(cs));
03230               }
03231             #endif
03232           }
03233 
03234 
03235         /* See if one of the send boxes is lost.
03236            All boxes sent before the deadline are considered lost.
03237            Lost boxes are recovered and added to the list of pending boxes.
03238            The processor to which the box was assigned is discarted for future
03239            jobs.
03240         */
03241         deadline=time(NULL)-(time_t)MPI_TREAT_BOX_TIMEOUT(cs);
03242         for(i=1;i<np;i++)
03243           {
03244             if ((!lost_packet[i])&& /*not already lost*/
03245                 (request[i]!=MPI_REQUEST_NULL)&& /*and we are waiting for a reply*/
03246                 (time_stamp[i]<deadline)) /*for too long actually*/
03247               {
03248                 /* we considere the sub-task as lost, we add the box for further process by 
03249                    another computer and we mark the current message as lost */
03250 
03251                 lost_packet[i]=TRUE; /* mark the packet as lost */
03252 
03253                 InitBox(cs->nvariables,NULL,&b); /*Recover it and put it again in the list of 
03254                                                    boxes to be processed*/
03255                 Buffer2Box(&c,&nr,buffers_out[i],&b); /* Error code (c) and additional information
03256                                                          (nr) are empty (this is a box whose process 
03257                                                          was not concluded)*/
03258             
03259                 NewLostBox(&(cs->st));
03260                 #if (_DEBUG>0)
03261                   fprintf(stderr,"  l[%u] (elapsed %lu)\n",i,time(NULL)-time_stamp[i]);
03262                 #endif
03263 
03264                 /* a time out tipically means a error in the simplex */
03265                 PostProcessBox(p,ERROR_IN_PROCESS,f_out,NULL,&boxes,&b,cs);
03266             
03267                 DeleteBox(&b);
03268 
03269                 in_process--; /* one less box is in process (Observe that the processors is
03270                                  not marked as available) */
03271               }
03272           }
03273 
03274         fflush(stderr);
03275 
03276       } while((!HeapEmpty(&boxes))||(in_process>0)); /*Until everything is completed (nothing in the
03277                                                        is to be processed and all boxes returned
03278                                                        from children)*/
03279 
03280       /* Send a magic packed to the child so that they kill themselves */
03281       
03282       for(i=1;i<np;i++)
03283         {
03284           if (request[i]!=MPI_REQUEST_NULL)
03285             {
03286               /*we have a pending communication with this processor -> cancel it*/
03287               MPI_Cancel(&(request[i]));
03288             }
03289           else
03290             { 
03291               /*nothing pending with this processors, just order it to die*/
03292               buffers_out[i][0]=-1.0; 
03293               MPI_Send(buffers_out[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD); 
03294             }
03295         }
03296 
03297       free(request);
03298       free(lost_packet);
03299       free(time_stamp);
03300 
03301       DeleteHeap(&boxes);
03302 
03303       if (f_out!=NULL)
03304         {
03305           fprintf(f_out,"\n\nCuik executed in %u (%u) child processors\n",available,np-1);
03306           PrintStatistics(f_out,&(cs->st));
03307         }
03308 
03309       DeleteStatistics(&(cs->st));
03310 
03311       for(i=1;i<np;i++)
03312         {
03313           free(buffers_in[i]);
03314           free(buffers_out[i]);
03315         }
03316         
03317       free(buffers_in);
03318       free(buffers_out);
03319     }
03320 }
03321 
03322 /*
03323   This is the process executed by each child process
03324 */
03325 void MPI_TreatBox(Tparameters *p,TCuikSystem *cs)
03326 {
03327   if (UpdateCuikSystem(p,cs))
03328     {
03329       boolean end;
03330       unsigned int n;
03331       double *buffer;
03332       unsigned int c,nr;
03333       Tbox b;
03334       MPI_Status status;
03335 
03336       InitBox(cs->nvariables,NULL,&b);
03337       n=GetBoxBufferSize(&b);
03338       NEW(buffer,n,double);
03339 
03340       /* A child can be in execution in computers not only devoted to cuik.
03341          We reduce the priority of the cuik process to allow other processes
03342          (those own by the owners of the machines) to run smoothly. 
03343          This way we can enlarge the cluster of procesors to almost all
03344          computers in our Lab.
03345          In the future we have to develop programs to check which computers
03346          are on and to add them into the machine list (i.e., the members of
03347          the cluster)
03348       */
03349       /*setpriority(PRIO_PROCESS,0,PRIO_MAX); */
03350 
03351       end=FALSE; /* While the kill buffer is not received */
03352          
03353       while(!end)
03354         {
03355           /* Get new box from the master */
03356           if (MPI_Recv(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD,&status)==MPI_SUCCESS)
03357             {
03358               /* The first double is used to send control messages between the 
03359                  scheduler and the slave. If negative, the slave dies*/
03360               if (buffer[0]<0) 
03361                 end=TRUE;
03362               else
03363                 {
03364                   /* If not the kill buffer, recover the box out of the buffer */
03365                   Buffer2Box(&c,&nr,buffer,&b);
03366 
03367                   ResetNBoxReductions(&(cs->st)); /* Let's count the box reductions for this 
03368                                                      box shrink only*/
03369 
03370                   #if (_DEBUG>1)
03371                     printf("Box from main processor:");
03372                     PrintBox(stdout,&b);
03373                     fflush(stdout);
03374                   #endif
03375 
03376                   /* And reduce it */
03377                   c=ReduceBox(p,~DUMMY_VAR,&b,cs);
03378 
03379                   #if (_DEBUG>1)
03380                     printf("Box out of ReduceBox (%u):",c);
03381                     PrintBox(stdout,&b);
03382                     fflush(stdout);
03383                   #endif
03384 
03385                   /* Then pack the result into another buffer */
03386                   Box2Buffer(c,GetNBoxReductions(&(cs->st)),buffer,&b);
03387 
03388                   /* and send it back to the master */
03389               
03390                   #if (_DEBUG>1)
03391                     if (MPI_Send(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD)!=MPI_SUCCESS)
03392                       printf("Sending to master failed\n");
03393                   #else
03394                     MPI_Send(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD);
03395                   #endif
03396                 
03397                 }
03398             }
03399           #if (_DEBUG>1)
03400           else
03401             printf("Receive from master failed\n");
03402           #endif
03403         }
03404 
03405       DeleteBox(&b);
03406       free(buffer);
03407     }
03408 }
03409 #endif
03410 
03411 
03412 
03413 /*
03414   Returns a box defined by the ranges for the variables given by the user in the
03415   input file. This is the initial search space.
03416  */
03417 void GenerateInitialBox(Tbox *box,TCuikSystem *cs)
03418 {
03419   BoxFromVariables(box,&(cs->orig_variables));
03420 }
03421 
03422 void ReGenerateOriginalBox(Tparameters *p,Tbox *boxS,Tbox *boxO,TCuikSystem *cs)
03423 {
03424   if (UpdateCuikSystem(p,cs))
03425     {
03426       BoxFromVariables(boxO,&(cs->orig_variables)); 
03427       UpdateOriginalFromSimple(boxS,boxO,cs->orig2sd); 
03428     }
03429   else
03430     Error("Inconsisten input cuiksystem");
03431 }
03432 
03433 /*
03434   Selects one dimension along which to split box 'b'. The dimension can
03435   be selected according to the size or according to the error that each
03436   variable induce in each equation.
03437   This is similar to ComputeSplitDimInt but the output is an index in 
03438   the original system and not in the simplified one
03439  */
03440 unsigned int ComputeSplitDim(Tparameters *p,Tbox *b,TCuikSystem *cs)
03441 {
03442   Tbox bsimp;
03443   unsigned int d;
03444 
03445   if (UpdateCuikSystem(p,cs))
03446     {
03447       SimpleFromOriginal(b,&bsimp,cs->orig2sd);
03448       d=GetVarIDInOriginal(ComputeSplitDimInt(p,&bsimp,cs),cs->orig2sd);
03449       DeleteBox(&bsimp);
03450     }
03451   else
03452     d=NO_UINT;
03453 
03454   return(d);
03455 }
03456 
03457 /*
03458   Returns TRUE if point stored in vector 'v' is included in box 'b'
03459   Dummy variables are not taken into account in this procedure.
03460 */
03461 boolean PointInSystemBox(Tvector *v,Tbox *b,TCuikSystem *cs)
03462 {
03463   unsigned int i,k,nv;
03464   double *val;
03465   boolean in;
03466 
03467   nv=NVariables(&(cs->orig_variables));
03468 
03469   if (nv!=GetBoxNIntervals(b))
03470     Error("Wrong box size in PointInSystemBox");
03471   
03472   k=0;
03473   in=TRUE;
03474   for(i=0;((in)&&(i<nv));i++)
03475     {
03476       if (!IsDummyVariable(i,&(cs->orig_variables)))
03477         {
03478           val=(double *)GetVectorElement(k,v);
03479           if (val==NULL) 
03480             Error("Vector with incorrect number of elements in PointInSystemBox");
03481           in=IsInside(*val,GetBoxInterval(i,b));
03482           k++;
03483         }
03484     }
03485   return(in);
03486 }
03487 
03488 /*
03489   Takes the center of the box and computes the error of this
03490   point when replaced into the system of equations.
03491   We use this function to check the validity of the outputs
03492   of Cuik.
03493  */
03494 double ErrorInSolution(Tbox *b,TCuikSystem *cs)
03495 {
03496   double *p; /*central point of the box*/
03497   unsigned int i;
03498   double e,max_error;
03499   Tequation *eq;
03500   unsigned int nv,ne;
03501 
03502   nv=NVariables(&(cs->orig_variables));
03503 
03504   if (nv!=GetBoxNIntervals(b))
03505     Error("Wrong box size in ErrorInSolution");
03506 
03507   NEW(p,nv,double);
03508 
03509   for(i=0;i<cs->orig_nvariables;i++)
03510     p[i]=IntervalCenter(GetBoxInterval(i,b));
03511 
03512   max_error=0.0;
03513   
03514   ne=NEquations(&(cs->orig_equations));
03515   for(i=0;i<ne;i++)
03516     {
03517       eq=GetEquation(i,&(cs->orig_equations));
03518  
03519       if ((GetEquationType(eq)==SYSTEM_EQ)&&
03520           (GetEquationCmp(eq)==EQU))
03521         {
03522           e=fabs(EvaluateEquation(p,eq)-GetEquationValue(eq)); 
03523 
03524           if (e>max_error) max_error=e;
03525         }
03526     }
03527 
03528   free(p);
03529   
03530   return(max_error);
03531 }
03532 
03533 
03534 double ErrorInInequalities(Tbox *b,TCuikSystem *cs)
03535 {
03536   unsigned int i,ne,nv,cmp;
03537   Tequation *eq;
03538   double e,maxError,r,v;
03539   double *p;
03540 
03541   nv=NVariables(&(cs->orig_variables));
03542 
03543   if (nv!=GetBoxNIntervals(b))
03544     Error("Wrong box size in ErrorInSolution");
03545 
03546   NEW(p,nv,double);
03547 
03548   for(i=0;i<cs->orig_nvariables;i++)
03549     p[i]=IntervalCenter(GetBoxInterval(i,b));
03550 
03551   ne=NEquations(&(cs->orig_equations));
03552   maxError=0;
03553   i=0;
03554   while (i<ne)
03555     {
03556       eq=GetEquation(i,&(cs->orig_equations));
03557 
03558       cmp=GetEquationCmp(eq);
03559       switch (cmp)
03560         {
03561         case LEQ:
03562           r=EvaluateEquation(p,eq);
03563           v=GetEquationValue(eq);
03564           e=(r<=v?0:r-v);
03565           break;
03566         case GEQ:
03567           r=EvaluateEquation(p,eq);
03568           v=GetEquationValue(eq);
03569           e=(r>=v?0:v-r);
03570           break;
03571         default:
03572           e=0;
03573           break;
03574         }
03575       if (e>maxError)
03576         maxError=e;
03577       i++;
03578     }
03579 
03580   free(p);
03581 
03582   return(maxError);
03583 }
03584 
03585 boolean CoordInequalitiesHold(Tbox *b,TCuikSystem *cs)
03586 {
03587   unsigned int i,ne,nv,cmp;
03588   Tinterval *is;
03589   boolean hold;
03590   Tequation *eq;
03591   Tinterval result;
03592 
03593   nv=NVariables(&(cs->orig_variables));
03594 
03595   if (nv!=GetBoxNIntervals(b))
03596     Error("Wrong box size in ErrorInSolution");
03597 
03598   is=GetBoxIntervals(b);
03599   
03600   ne=NEquations(&(cs->orig_equations));
03601   hold=TRUE;
03602   i=0;
03603   while((i<ne)&&(hold))
03604     {
03605       eq=GetEquation(i,&(cs->orig_equations));
03606       if (GetEquationType(eq)==COORD_EQ)
03607         {
03608           cmp=GetEquationCmp(eq);
03609           switch (cmp)
03610             {
03611             case LEQ:
03612               EvaluateEquationInt(is,&result,eq);
03613               hold=(UpperLimit(&result)<=GetEquationValue(eq));
03614               break;
03615             case GEQ:
03616               EvaluateEquationInt(is,&result,eq);
03617               hold=(LowerLimit(&result)>=GetEquationValue(eq));
03618               break;
03619             }
03620         }
03621       i++;
03622     }
03623   return(hold);
03624 }
03625 
03626 
03627 /*
03628   Prints the information stored in the cuiksystem
03629   It prints it in a form than can be parsed again.
03630 */
03631 void PrintCuikSystem(Tparameters *p,FILE *f,TCuikSystem *cs)
03632 {
03633   unsigned int nv;
03634   char **varNames;
03635 
03636   PrintVariables(f,&(cs->orig_variables));
03637   
03638   nv=NVariables(&(cs->orig_variables));
03639   NEW(varNames,nv,char *);
03640   GetVariableNames(varNames,&(cs->orig_variables));
03641   PrintEquations(f,varNames,&(cs->orig_equations));
03642   if (cs->searchMode==MINIMIZATION_SEARCH)
03643     {
03644       fprintf(f,"\n[SEARCH]\n\n MIN ");
03645       PrintMonomials(f,varNames,&(cs->orig_eqMin));
03646     }
03647   free(varNames);  
03648   fprintf(f,"\n\n");
03649 }
03650 
03651 /*
03652   Prints the information stored in the cuiksystem together with the simplified
03653   CuikSystem.
03654   It prints it in a form than can be parsed again.
03655 */
03656 void PrintCuikSystemWithSimplification(Tparameters *p,FILE *f,TCuikSystem *cs)
03657 {
03658   unsigned int nv;
03659   char **varNames;
03660 
03661   #if (_DEBUG>1)
03662     fprintf(f,"%%****************************************\n");
03663     fprintf(f,"%% Original system \n");
03664     PrintVariables(f,&(cs->orig_variables));
03665     
03666     nv=NVariables(&(cs->orig_variables));
03667     NEW(varNames,nv,char *);
03668     GetVariableNames(varNames,&(cs->orig_variables));
03669     PrintEquations(f,varNames,&(cs->orig_equations));
03670     if (cs->searchMode==MINIMIZATION_SEARCH)
03671       {
03672         fprintf(f,"\n[SEARCH]\n\n MIN ");
03673         PrintMonomials(f,varNames,&(cs->orig_eqMin));
03674       }
03675     fprintf(f,"\n\n");
03676     free(varNames);
03677   #endif
03678 
03679   if (UpdateCuikSystem(p,cs))
03680     {
03681       fprintf(f,"%%****************************************\n");
03682       fprintf(f,"%% Simplified system \n");
03683       fprintf(f,"%% SIMPLIFICATION_LEVEL: %u\n",
03684               (unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p)));
03685       PrintMapping(f,cs->orig2sd);
03686       PrintVariables(f,&(cs->variables));
03687 
03688       nv=NVariables(&(cs->variables));
03689       NEW(varNames,nv,char *);
03690       GetVariableNames(varNames,&(cs->variables));
03691       PrintEquations(f,varNames,&(cs->equations));
03692       if (cs->searchMode==MINIMIZATION_SEARCH)
03693         {
03694           fprintf(f,"\n[SEARCH]\n\n MIN ");
03695           PrintMonomials(f,varNames,&(cs->eqMin));
03696         }
03697       free(varNames);
03698     }
03699   else
03700     fprintf(f,"INCONSISTENT INPUT CUIK SYSTEM\n");
03701 }
03702 
03703 void SaveCuikSystemSimplification(Tparameters *p,FILE *f,TCuikSystem *cs)
03704 {
03705   if (UpdateCuikSystem(p,cs))
03706     SaveMapping(f,cs->orig2sd);
03707   else
03708     fprintf(f,"INCONSISTENT INPUT CUIK SYSTEM\n");
03709 }
03710 
03711 /*
03712   Destructor of the cuiksystem structure.
03713 */
03714 void DeleteCuikSystem(TCuikSystem *cs)
03715 { 
03716   DeleteVariables(&(cs->orig_variables));
03717   DeleteEquations(&(cs->orig_equations));  
03718   DeleteStatistics(&(cs->st)); 
03719 
03720   UnUpdateCuikSystem(cs);
03721 
03722   cs->empty=TRUE;
03723 }