cuiksystem.c
Go to the documentation of this file.
1 #include "cuiksystem.h"
2 
3 #include "error.h"
4 #include "boolean.h"
5 #include "defines.h"
6 #include "box_list.h"
7 #include "box_heap.h"
8 #include "simplex.h"
9 #include "random.h"
10 #include "filename.h"
11 #include "algebra.h"
12 
13 #include <stdlib.h>
14 
15 #include <math.h>
16 #include <string.h>
17 #include <sys/time.h>
18 #include <signal.h>
19 #if (_USE_MPI)
20  #include <mpi.h>
21  #include <sys/resource.h>
22  #include <time.h>
23  #include <unistd.h>
24 #endif
25 
26 
27 
37 /* Internal functions */
38 
56 
69 
70 
88 double EvaluateEqMin(void *b,void *cs);
89 
109 unsigned int ReduceBoxEquationWise(Tparameters *p,Tbox *b,TCuikSystem *cs);
110 
139 unsigned int ReduceBox(Tparameters *p,unsigned int varMask,Tbox *b,TCuikSystem *cs);
140 
162 void PostProcessBox(Tparameters *p,unsigned int c,
163  FILE *f_out,
164  Tlist *sol,
165  Theap *boxes,
166  Tbox *b,
167  TCuikSystem *cs);
168 
181 
182 
213  boolean *replaced,TLinearConstraint *lc,
214  Tbox *borig,TCuikSystem *cs);
215 
260 boolean CSRemoveLCVars(Tparameters *p,unsigned int simplificationLevel,
261  unsigned int level,boolean *changed,
262  boolean *replaced,TLinearConstraint *lc,
263  Tbox *borig,TCuikSystem *cs);
289 
307 void AddJacobianEquationsInt(Tparameters *p,boolean *selectedVars,TJacobian *J,
308  TCuikSystem *cs);
309 
327 
342 
362 unsigned int ComputeSplitDimInt(Tparameters *p,Tbox *b,TCuikSystem *cs);
363 
383 void SaveCSState(char *fname,Tlist *lb,TCuikSystem *cs);
384 
398 void LoadCSState(char *fname,Tlist *lb,TCuikSystem *cs);
399 
400 
401 /************************************************************************/
402 /************************************************************************/
403 /************************************************************************/
404 
405 /*
406  The equation is dummified and the resulting equations and new variables
407  are added to the cuik system.
408 
409  Dummification is performed in the last step of the simplification and, thus,
410  this function operates in the sets of simplified equations and variables
411 
412  Dummification consists in changing all monomials of type x^2 or x*y by new
413  variables 'z' and adding the corresponding equations (z=x^2 or z=x*y) to
414  the system.
415 
416  The level of dummification is controlled by the 'dummify' parameter.
417 
418  This internal function is hidden to the user. In this way dummification is
419  applied only after the system simplification.
420  See AddEquation2CS and SimplifyCuikSystem.
421 */
423 {
424  if (eq!=NULL)
425  {
426  unsigned int nf;
427  unsigned int i,nv,mv;
428  Tvariable_set *vars;
429  unsigned int dummify;
430  unsigned int eqType;
431 
432  dummify=(unsigned int)(GetParameter(CT_DUMMIFY,p));
433 
434  vars=GetEquationVariables(eq);
435  eqType=GetEquationType(eq);
436 
437  nv=VariableSetSize(vars);
438  mv=NVariables(&(cs->variables));
439  for(i=0;i<nv;i++)
440  {
441  if (GetVariableN(i,vars)>=mv)
442  Error("Unknown variable in AddEquation2CS");
443  }
444 
445  nf=GetNumMonomials(eq);
446  if (nf>0)
447  {
448  boolean keep=TRUE; /* True if the equation is kept in its original form */
449 
450  /* Dummy equations are not dummified again */
451  /*dummify equations with just one monomial introduce a
452  too simple variable x=ct that is not simplified since
453  the dummifications is performed after the simplification. */
454  if ((eqType==DUMMY_EQ)||(GetNumMonomials(eq)==1)||(GetEquationOrder(eq)>2))
455  keep=TRUE;
456  else
457  {
458  switch (dummify)
459  {
460  case 0:
461  keep=TRUE;
462  break;
463  case 1:
464  keep=((LinearEquation(eq))||
465  (ParabolaEquation(eq))||
466  (SaddleEquation(eq))||
467  (CircleEquation(eq))||
468  (SphereEquation(eq)));
469  break;
470  case 2:
471  keep=((LinearEquation(eq))||
472  (ParabolaEquation(eq))||
473  (SaddleEquation(eq)));
474  break;
475  case 3:
476  keep=((LinearEquation(eq))||
477  (ParabolaEquation(eq))||
478  (SaddleEquation(eq))||
479  (CircleEquation(eq))||
480  (SphereEquation(eq))||
481  (GetEquationCmp(eq)!=EQU)); /*Inequalities are kept in original form*/
482 
483  break;
484  case 4:
485  keep=((LinearEquation(eq))||
486  (ParabolaEquation(eq))||
487  (SaddleEquation(eq))||
488  (GetEquationCmp(eq)!=EQU)); /*Inequalities are kept in original form*/
489  break;
490  default:
491  Error("Undefined value for DUMMIFY parameter");
492  }
493  }
494 
495  if (keep)
496  AddEquation(eq,&(cs->equations));
497  else
498  {
499  unsigned int j,p,vid1,vid2,vid3;
500  Tmonomial *f,fnew;
501  Tequation eqnew; /* Bilinear and quadratic monomials produce new auxiliary equations */
502  Tequation eqlineal; /* The original equation is transformed into a lineal equation */
503  char *vname;
504  Tinterval range;
505  Tvariable v;
506  char *n1,*n2;
507 
508  InitEquation(&eqlineal);
509 
510  for(j=0;j<nf;j++) /* For all monomials in the equation to be dummified */
511  {
512 
513  f=GetMonomial(j,eq);
514  vars=GetMonomialVariables(f);
515  nv=VariableSetSize(vars);
516 
517  switch(nv)
518  {
519  case 1: /*A single variable in the monomial*/
520  if (GetVariableFunctionN(0,vars)!=NFUN)
521  AddMonomial(f,&eqlineal);
522  else
523  {
524  p=GetVariablePowerN(0,vars);
525 
526  switch(p)
527  {
528  case 1: /*One variable with degree 1*/
529  /* A linear monomial: just add it to the linear equation*/
530 
531  AddMonomial(f,&eqlineal); /* A copy of monomial 'f' is stored in eqlineal*/
532  break;
533 
534  case 2:/*One varialbe With degree 2*/
535  /* Add a linear monomial to eqlinear with a dummy variable
536  and add the corresponding parabola equation*/
537 
538  vid1=GetVariableN(0,vars);
539 
540  /* Generate a new variable dummy that will stand for x^2 */
541  n1=GetVariableName(GetVariable(vid1,&(cs->variables)));
542  NEW(vname,strlen(n1)+20,char);
543  sprintf(vname,"dummy_%s_2",n1);
544 
545  vid2=GetVariableID(vname,&(cs->variables));
546 
547  if (vid2==NO_UINT)
548  {
549  /* if the dummy variable is a new one, add the corresponding
550  dummy equation to the system */
551 
552  NewVariable(DUMMY_VAR,vname,&v);
553  IntervalPow(GetVariableInterval(GetVariable(vid1,&(cs->variables))),2,&range);
554  SetVariableInterval(&range,&v);
555 
556  vid2=AddVariable(&v,&(cs->variables));
557  DeleteVariable(&v);
558 
559  /* Generate a new equation x^2-dummy=0 */
560  InitEquation(&eqnew);
561 
562  InitMonomial(&fnew);
563  AddVariable2Monomial(NFUN,vid1,2,&fnew);
564  AddCt2Monomial( 1.0,&fnew);
565  AddMonomial(&fnew,&eqnew);
566  DeleteMonomial(&fnew);
567 
568  InitMonomial(&fnew);
569  AddVariable2Monomial(NFUN,vid2,1,&fnew);
570  AddCt2Monomial(-1.0,&fnew);
571  AddMonomial(&fnew,&eqnew);
572  DeleteMonomial(&fnew);
573 
574  SetEquationCmp(EQU,&eqnew);
575  SetEquationValue(0.0,&eqnew);
576  /*The derive equations is of the same type as the origiona one*/
577  SetEquationType(DUMMY_EQ,&eqnew);
578 
579  AddEquation(&eqnew,&(cs->equations));
580  DeleteEquation(&eqnew);
581  }
582  free(vname);
583 
584  /*Now add the lineal monomial using the new dummy variable to eqlineal*/
585  InitMonomial(&fnew);
586  AddVariable2Monomial(NFUN,vid2,1,&fnew);
587  AddCt2Monomial(GetMonomialCt(f),&fnew);
588  AddMonomial(&fnew,&eqlineal);
589  DeleteMonomial(&fnew);
590  break;
591 
592  default:
593  Error("The input system to DummifyCuikSystem is not in canonical form");
594  break;
595  }
596  }
597  break;
598 
599  case 2: /*Two variables in the monomial*/
600  if ((GetVariableFunctionN(0,vars)!=NFUN)||
601  (GetVariableFunctionN(1,vars)!=NFUN))
602  AddMonomial(f,&eqlineal);
603  else
604  {
605  if ((GetVariablePowerN(0,vars)==1)&&
606  (GetVariablePowerN(1,vars)==1)) /*The two of them with degree 1*/
607  {
608  /*Get the two variables involved in the product we have to rewrite*/
609  vid1=GetVariableN(0,vars);
610  vid2=GetVariableN(1,vars);
611 
612  /*Generate a new dummy variable*/
613  n1=GetVariableName(GetVariable(vid1,&(cs->variables)));
614  n2=GetVariableName(GetVariable(vid2,&(cs->variables)));
615  NEW(vname,strlen(n1)+strlen(n2)+20,char);
616  sprintf(vname,"dummy_%s_%s",n1,n2);
617 
618  vid3=GetVariableID(vname,&(cs->variables));
619  if (vid3==NO_UINT)
620  {
621 
622  NewVariable(DUMMY_VAR,vname,&v);
625  &range);
626  SetVariableInterval(&range,&v);
627 
628  vid3=AddVariable(&v,&(cs->variables));
629  DeleteVariable(&v);
630 
631  /* Generate the dummy equation X*Y-dummy=0*/
632  InitEquation(&eqnew);
633 
634  InitMonomial(&fnew);
635  AddVariable2Monomial(NFUN,vid1,1,&fnew);
636  AddVariable2Monomial(NFUN,vid2,1,&fnew);
637  AddCt2Monomial( 1.0,&fnew);
638  AddMonomial(&fnew,&eqnew);
639  DeleteMonomial(&fnew);
640 
641  InitMonomial(&fnew);
642  AddVariable2Monomial(NFUN,vid3,1,&fnew);
643  AddCt2Monomial(-1.0,&fnew);
644  AddMonomial(&fnew,&eqnew);
645  DeleteMonomial(&fnew);
646 
647  SetEquationCmp(EQU,&eqnew);
648  SetEquationValue(0.0,&eqnew);
649  /*The derive equations is of the same type as the origiona one*/
650  SetEquationType(DUMMY_EQ,&eqnew);
651 
652  AddEquation(&eqnew,&(cs->equations));
653  DeleteEquation(&eqnew);
654  }
655  free(vname);
656 
657  /*Now add the lineal monomial using the new dummy variable to eqlienal*/
658  InitMonomial(&fnew);
659  AddVariable2Monomial(NFUN,vid3,1,&fnew);
660  AddCt2Monomial(GetMonomialCt(f),&fnew);
661  AddMonomial(&fnew,&eqlineal);
662  DeleteMonomial(&fnew);
663  }
664  else
665  /* One of the 2 variables in the monomial has degree >1 */
666  /* Right now this should never happen since equations
667  with order>2 are directly added to the outpu system */
668  Error("The input system to DummifyCuikSystem is not in canonical form");
669  }
670  break;
671 
672  default:
673  /* A monomial with more than 2 variables */
674  /* Right now this should never happen since equations
675  with order>2 are directly added to the outpu system */
676  Error("The input system to DummifyCuikSystem is not in canonical form");
677  }
678 
679  } /* Proceed with next monomial in the under-dummification equation*/
680 
681  /* The linearized original equation is added to the system */
682 
683  SetEquationCmp(GetEquationCmp(eq),&eqlineal);
684  SetEquationValue(GetEquationValue(eq),&eqlineal);
685  /*The resulting lineal equation is of the same type as the original equation*/
686  SetEquationType(eqType,&eqlineal);
687 
688  AddEquation(&eqlineal,&(cs->equations));
689  DeleteEquation(&eqlineal);
690  }
691  }
692  }
693 }
694 
696 {
697  if (cs->scalar)
698  {
699  unsigned int i,neq;
700  Tequations eqs;
701 
702  CopyEquations(&eqs,&(cs->equations));
703  DeleteEquations(&(cs->equations));
704  InitEquations(&(cs->equations));
705 
706  neq=NEquations(&eqs);
707  for(i=0;i<neq;i++)
708  DummifyAndAddEquation(p,GetEquation(i,&eqs),cs);
709 
710  DeleteEquations(&eqs);
711  }
712 }
713 
715 {
716  boolean empty;
717  boolean small;
718  boolean significantReduction;
719  Tbox b_orig;
720  unsigned int i,j;
721  double rho,smallSigma,epsilon;
722  double mi_r;
723  double reduction;
724 
725  rho=GetParameter(CT_RHO,p);
726  epsilon=GetParameter(CT_EPSILON,p);
727  smallSigma=GetParameter(CT_SMALL_SIGMA,p);
728 
729  /*default values*/
730  empty=FALSE;
731  significantReduction=FALSE;
732  small=FALSE;
733 
734  #if (_DEBUG>2)
735  printf(" Croping box: ");
736  PrintBox(stdout,b);
737  printf(" Size in: %g\n",GetBoxSize(cs->systemVar,b));
738  #endif
739 
740  do {
741  CopyBox(&b_orig,b);
742 
743  for(j=0;((!empty)&&(j<cs->nequations));j++)
744  {
745  #if (_DEBUG>5)
746  printf(" Croping with equation %u: \n",j);
747  printf(" Input box: ");
748  PrintBox(stdout,b);
749  printf(" s: %g v:%g\n",GetBoxSize(NULL,b),GetBoxVolume(NULL,b));
750  #endif
751  if (CropEquation(j,ANY_TYPE_VAR,epsilon,rho,b,&(cs->variables),&(cs->equations))==EMPTY_BOX)
752  empty=TRUE;
753  #if (_DEBUG>5)
754  if (empty)
755  printf(" Empty output box\n");
756  else
757  {
758  printf(" Output box: ");
759  PrintBox(stdout,b);
760  printf(" s: %g v:%g\n",GetBoxSize(NULL,b),GetBoxVolume(NULL,b));
761  }
762  #endif
763  }
764 
765  if (!empty)
766  {
767  mi_r=1.0;
768  for(i=0;i<cs->nvariables;i++)
769  {
770  /*variables of all types are affected by crop*/
771  reduction=IntervalSize(GetBoxInterval(i,b))/IntervalSize(GetBoxInterval(i,&b_orig));
772  if (reduction<mi_r) mi_r=reduction;
773  }
774 
775  significantReduction=(mi_r<rho);
776  small=(GetBoxSize(cs->systemVar,b)<=smallSigma);
777 
778  #if (_DEBUG>2)
779  printf(" Crop reduction: %f\n",mi_r);
780  if (small)
781  printf(" Tiny boxes are not reduced any more\n");
782  else
783  {
784  if (significantReduction)
785  printf(" Large reduction. Cropping again\n");
786  }
787  #endif
788  }
789  DeleteBox(&b_orig);
790 
791  } while ((!empty)&&(!small)&&(significantReduction));
792 
793  #if (_DEBUG>2)
794  if (empty)
795  printf(" Empty in Crop\n");
796  else
797  {
798  printf(" Croped box: ");
799  PrintBox(stdout,b);
800  printf(" Size out: %g\n",GetBoxSize(cs->systemVar,b));
801  }
802  #endif
803 
804  if (empty)
805  return(EMPTY_BOX);
806  else
807  return(REDUCED_BOX);
808 }
809 
810 /*
811  This is the basic function of the solver. This function includes the
812  ShrinkBox procedure described in our papers plus a loop interating
813  ShrinkBox as far as the box is significantly reduced (and still not empty).
814 
815  Thus, ReduceBox takes an input box 'b' and reduces it as much as possible by removing
816  parts that do not include any solution point.
817  It returns information about what happened in the box shrinking process
818 
819  ERROR_IN_PROCESS: When one of the simplex failed due to numerical inestabilities
820  The better the simplex implementation the less likely this
821  output.
822 
823  EMPTY_BOX: The box includes no solution. In this case the output box is
824  undefined (it includes empty intervals).
825 
826  REDUCED_BOX: The box was reduced and it has to be processed further to determine
827  if it includes any solution.
828 
829  REDUCED_BOX_WITH_SOLUTION: The box was been reduced and one of the reduction
830  steps was contractive. This indicates the box
831  includes a solution point.
832  */
833 unsigned int ReduceBox(Tparameters *p,unsigned int varMask,Tbox *b,TCuikSystem *cs)
834 {
835  /*The box can only be reduced if we have constraints*/
836  if (cs->simp_nequations==0)
837  return(REDUCED_BOX);
838  else
839  {
840  boolean empty;
841  boolean significantReduction;
842  boolean small;
843  boolean hasSolution;
844  boolean err;
845  boolean boxOK;
846  unsigned int e;
847  double mi_r,ma_s;
848  double reduction,size;
849  unsigned int i,j;
850  Tbox b_orig;
851  TSimplex lp;
852  double epsilon,smallSigma,rho,lr2tm_q,lr2tm_s;
853  unsigned int safeSimplex;
854  boolean repeatLoop;
855 
856  if ((!cs->updated)||(!cs->consistent))
857  Error("Non-updated/consistent CS in ReduceBox");
858 
859  epsilon=GetParameter(CT_EPSILON,p);
860  smallSigma=GetParameter(CT_SMALL_SIGMA,p);
861  rho=GetParameter(CT_RHO,p);
862  lr2tm_q=GetParameter(CT_LR2TM_Q,p);
863  lr2tm_s=GetParameter(CT_LR2TM_S,p);
864  safeSimplex=(unsigned int)(GetParameter(CT_SAFE_SIMPLEX,p));
865 
866  /*default values*/
867  empty=FALSE;
868  hasSolution=FALSE;
869  err=FALSE;
870  boxOK=TRUE;
871  small=FALSE;
872  significantReduction=FALSE;
873  repeatLoop=FALSE;
874 
875  do {
876  #if (_DEBUG>2)
877  printf("\n Go for box reduction via crop+simplex\n");
878  printf(" InputBox: "); PrintBox(stdout,b);
879  printf(" s: %g v:%g\n",GetBoxSize(NULL,b),GetBoxVolume(NULL,b));
880  #endif
881 
882  /*****************************************************************/
883  /* One step of box reduction */
884 
885  /*#if ((!_USE_MPI)&&(_DEBUG==1))*/
886  #if ((!_USE_MPI)&&(_DEBUG>1))
887  fprintf(stderr,".");fflush(stderr);
888  #endif
889 
890  NewBoxReduction(&(cs->st));
891 
892  /* First we do an equation wise reduction of the ranges -> Crop equation
893  repeated for each equation as far as we get a significant box reduction */
894 
895  empty=(ReduceBoxEquationWise(p,b,cs)==EMPTY_BOX);
896 
897  /* If the equation-wise reduction gives a full box, proceed with the global
898  test based on linear programming */
899 
900  if (empty)
901  repeatLoop=FALSE; /*There is no need to iterate*/
902  else
903  {
904  SimplexCreate(epsilon,cs->nvariables,&lp);
905 
906  /* Add the linear constraints bounding the equations. This include
907  croping the input ranges if necessary */
908 
909  for(j=0;((!empty)&&(j<cs->nequations));j++)
910  {
911  if (!AddEquation2Simplex(j,
912  lr2tm_q,lr2tm_s,
913  epsilon,safeSimplex,rho,
914  b,&(cs->variables),
915  &lp,&(cs->equations)))
916  empty=TRUE;
917  }
918 
919  boxOK=TRUE;
920  err=FALSE;
921  small=FALSE;
922  significantReduction=FALSE;
923 
924  /* Use the simplex to reduce the ranges for the variables */
925  if ((!empty)&&(SimplexNRows(&lp)>0)) /* In extreme cases the simplex tableau can be empty
926  and then nothings can be reduced*/
927  {
928  /* Store the original box to check the actual reduction */
929  CopyBox(&b_orig,b);
930 
931  #if (_SIMPLEX_ENGINE!=_CLP) /* in CLP Reset Simplex has no effect */
932  ResetSimplex(&lp);
933  #endif
934 
935  for(i=0;((boxOK)&&(i<cs->nvariables));i++)
936  {
937  /* The crop takes care of reducing the ranges of the dummy
938  variables in function of the non dummy ones (system,
939  secondary and cartesian).
940  */
941 
942  if ((cs->varType[i]&varMask)&&(!SimplexColEmpty(i,&lp)))
943  {
944  /*Reduce the ranges for variable 'i'*/
945  e=ReduceRange(epsilon,safeSimplex,i,b,&lp);
946  boxOK=(e==REDUCED_BOX);
947  }
948  }
949 
950  /* Analize the output out of the range reduction */
951  if (boxOK)
952  {
953  /* Compute the minimum reduction ratio for all ranges. The smaller
954  the reductin ratio, the maximal the box shrink for that dimension*/
955  mi_r=1.0;
956  ma_s=0.0;
957  for(i=0;i<cs->nvariables;i++)
958  {
959  if (cs->notDummyVar[i])
960  {
961  size=IntervalSize(GetBoxInterval(i,b));
962  if (size>ma_s) ma_s=size;
963 
964  reduction=size/IntervalSize(GetBoxInterval(i,&b_orig));
965  if (reduction<mi_r) mi_r=reduction;
966  }
967  }
968 
969  /* If the output box is fully included in the input one this means
970  the box includes a solution (for sure) */
971  if ((ma_s<lr2tm_q)&&(ma_s<lr2tm_s)&&
972  (BoxInclusion(cs->systemVar,b,&b_orig)))
973  {
974  hasSolution=TRUE;
975  #if (!_USE_MPI)
976  fprintf(stderr,"(>!<)");
977  #endif
978  }
979 
980  small=(ma_s<=smallSigma);
981  significantReduction=(mi_r<rho);
982  }
983  else
984  {
985  empty=(e==EMPTY_BOX);
986  err=(e==ERROR_IN_PROCESS);
987  }
988 
989  DeleteBox(&b_orig);
990  }
991 
992  repeatLoop=((!empty)&&(!err)&&(!small)&&(significantReduction));
993 
994  SimplexDelete(&lp);
995 
996  #if (_DEBUG>2)
997  if (empty)
998  printf(" Empty\n");
999  else
1000  {
1001  if (err)
1002  printf(" Simplex Error\n");
1003  else
1004  {
1005  printf(" OutputBox: "); PrintBox(stdout,b);
1006  printf(" Reduction -> %f\n",mi_r);
1007 
1008  printf(" Size after reduction: %g\n ",GetBoxSize(cs->systemVar,b));
1009  printf(" Volume after reduction: %g\n ",GetBoxVolume(cs->systemVar,b));
1010 
1011  if (significantReduction)
1012  printf(" Large enough reduction-> Try again all equations\n");
1013  else
1014  printf(" Not enough reduction.\n");
1015  }
1016  }
1017  #endif
1018 
1019  } /* end if not empty after */
1020 
1021  } while(repeatLoop);
1022 
1023  if (err)
1024  e=ERROR_IN_PROCESS;
1025  else
1026  {
1027  if (empty)
1028  e=EMPTY_BOX;
1029  else
1030  {
1031  /* If at least on step was a contraction this means
1032  there is a solution inside the box*/
1033  if (hasSolution)
1035  else
1036  e=REDUCED_BOX;
1037  }
1038  }
1039 
1040  return(e);
1041  }
1042 }
1043 
1044 /*
1045  This procedure is called just after using ReduceBox to analyzed what
1046  happened with the box and what to do next.ç 'c' is the return code out of Reduce Box If the box is small (max side size smaller than sigma), we consider it a solution and we store it in the list 'sol' (if defined), we save the solution into 'f_out' (if defined). Otherwise, we split the box in two sub-boxes and we store them in list 'boxes' The dimension along which the box is splitte is determined according to parameter 'error_split'. The two sub-boxes are added to 'boxes' in the first of in the last position according to parameter 'depth_first'. */ void PostProcessBox(Tparameters *p, unsigned int c, FILE *f_out, Tlist *sol, Theap *boxes,Tbox *b, TCuikSystem *cs) { boolean empty,small; Tbox b_orig; double sigma; unsigned int nNewton; double epsilon; empty=(c==EMPTY_BOX); if (empty) { NewEmptyBox(&(cs->st)); #if (_DEBUG>1) printf(" The box is empty -> deleted\n"); #endif #if (_DEBUG>0) fprintf(stderr,"e\n"); #endif } else { /* c==REDUCED_BOX or c==REDUCED_BOX_WITH_SOLUTION or c==ERROR_IN_PROCESS*/ #if (_DEBUG>1) printf(" Resulting box: "); PrintBox(stdout,b); #endif #if (_DEBUG>0) fprintf(stderr,"<%g %g>", GetBoxVolume(cs->systemVar,b), GetBoxSize(cs->systemVar,b)); #endif /* We initialize a box in the original system and set the default ranges (ranges in case the variable in the original system is not in the simplified one... this is not likely to occur here but in the system to sybsystem relation but in this way the interface is the same)*/ BoxFromVariables(&b_orig,&(cs->orig_variables)); UpdateOriginalFromSimple(b,&b_orig,cs->orig2sd); #if (_DEBUG>1) printf(" Original box: "); PrintBox(stdout,&b_orig); #endif epsilon=GetParameter(CT_EPSILON,p); nNewton=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p); if ((nNewton>0)&&(f_out!=NULL)&&(GetBoxSize(cs->systemVar,b)>epsilon)) { double *sol; Tbox b_sol; NEW(sol,cs->orig_nvariables,double); if ((CuikNewtonInBox(p,&b_orig,sol,&b_sol,cs)&(CONVERGED_IN_BOX|CONVERGED_IN_GLOBAL))>0) { fprintf(f_out,"Newton [s:%f v:%g l:%u t:%g]: ", GetBoxSize(cs->systemVar,b), GetBoxVolume(cs->systemVar,b), GetBoxLevel(b), GetElapsedTime(&(cs->st))); PrintBoxSubset(f_out,cs->orig_notDummyVar,cs->orig_varNames,&b_sol); } free(sol); DeleteBox(&b_sol); fflush(f_out); } sigma=GetParameter(CT_SIGMA,p); /*The original system can have variables not included in the simplified one. For instance, variables not in the system equations due to the particular constants of the problem under analysis are eliminated, even though they appear in dummy equations (this is common when ROT_REP=1, see link.h). Those removed variables are never reduced and thus, the original box never reduces below sigma. This is why we use the simplified box (i.e., the one we actually reduce) to assess whether or not we have a solution. */ small=(GetBoxSize(cs->systemVar,b)<=sigma); if (small) { #if (_DEBUG>1) printf(" The box is a solution (size %g vs [%g]) ->add to the list of solutions\n", GetBoxSize(cs->orig_systemVar,&b_orig),sigma); #endif NewSolutionBox((c==REDUCED_BOX_WITH_SOLUTION), GetBoxVolume(cs->orig_systemVar,&b_orig), GetBoxDiagonal(cs->orig_systemVar,&b_orig), &(cs->st)); if(c==ERROR_IN_PROCESS) NewRBError(&(cs->st)); #if (_DEBUG>0) if(c==REDUCED_BOX_WITH_SOLUTION) fprintf(stderr,"S\n"); else fprintf(stderr,"s\n"); #endif if (f_out!=NULL) { if(c==ERROR_IN_PROCESS) fprintf(f_out," E"); fprintf(f_out," %3u (err:%g", GetNSolutionBoxes(&(cs->st)), ErrorInSolution(&b_orig,cs)); #if (_DEBUG>1) printf(" Solution number %u with erorr %g\n", GetNSolutionBoxes(&(cs->st)), ErrorInSolution(&b_orig,cs)); #endif if (cs->searchMode==MINIMIZATION_SEARCH) fprintf(f_out," min:%g",EvaluateEqMin((void *)b,(void *)cs)); fprintf(f_out," tm:%g):",GetElapsedTime(&(cs->st))); if (c==REDUCED_BOX_WITH_SOLUTION) fprintf(f_out," <S> "); /*The output does not include the dummy variables (they are not relevant any more)*/ PrintBoxSubset(f_out,cs->orig_notDummyVar,cs->orig_varNames,&b_orig); fflush(f_out); } if (sol!=NULL) { Tbox *sb; NEW(sb,1,Tbox); CopyBox(sb,&b_orig); AddLastElement((void *)sb,sol); } /*If we want to ad box to a solution list, we have to copy 'b' somewhere else ('b' is delete after this function !)*/ } else { /* Non empty large box or error in ReduceBox */ Tbox b1,b2; unsigned int d; #if (_DEBUG>1) printf(" Box size : %g vs. %g\n",GetBoxSize(cs->orig_systemVar,&b_orig),sigma); printf(" The box has to be splitted (and deleted)\n"); #endif NewSplittedBox(&(cs->st)); d=ComputeSplitDimInt(p,b,cs); SplitBox(d,CUT_POINT,&b1,&b2,b); #if (_DEBUG>1) printf(" Splitting along dimension %u (internal)\n",d); if (cs->searchMode==MINIMIZATION_SEARCH) printf(" Box penalgy : %g\n",EvaluateEqMin((void *)&b1,(void *)cs)); printf(" SubBox:"); PrintBox(stdout,&b1); if (cs->searchMode==MINIMIZATION_SEARCH) printf(" Box penalty : %g\n",EvaluateEqMin((void *)&b2,(void *)cs)); printf(" SubBox:"); PrintBox(stdout,&b2); #endif AddBox2HeapOfBoxes(&b1,boxes); AddBox2HeapOfBoxes(&b2,boxes); DeleteBox(&b1); DeleteBox(&b2); if (c==ERROR_IN_PROCESS) { #if (_DEBUG>0) fprintf(stderr,"E[%u]\n",d); #endif #if (_DEBUG>1) printf(" Splitted due to simplex error\n"); #endif NewRBError(&(cs->st)); } #if (_DEBUG>0) else fprintf(stderr,"b[%u]\n",d); #endif } DeleteBox(&b_orig); } } void CSRemoveUnusedVars(Tparameters *p,TCuikSystem *cs) { unsigned int i,vt; double epsilon; epsilon=GetParameter(CT_EPSILON,p); /*We proceed back to front because removing a variable change the indexes of variables above it.*/ i=NVariables(&(cs->variables)); while(i>0) { i--; vt=GetVariableTypeN(i,&(cs->variables)); if ((!VarIncluded(i,GetEquationVariables(&(cs->orig_eqMin))))&& (((vt==DUMMY_VAR)&&(!UsedVarInNonDummyEquations(i,&(cs->equations))))|| ((vt!=SYSTEM_VAR)&&(!UsedVarInEquations(i,&(cs->equations)))))) { /* ... Therefore, we can still have dummy equations with the non-used variables*/ RemoveEquationsWithVar(epsilon,i,&(cs->equations)); RemoveVariable(i,&(cs->variables)); } } } boolean CSRemoveVarsWithCtRange(Tparameters *p, boolean *replaced,TLinearConstraint *lc, Tbox *borig,TCuikSystem *cs) { boolean found,hold; unsigned int nv,origID1; unsigned int id1; char *name1; double epsilon; double ct2; Tinterval *range; epsilon=GetParameter(CT_EPSILON,p); hold=TRUE; do { found=FALSE; /* A variable with a ct range can be removed */ nv=NVariables(&(cs->variables)); id1=0; while((!found)&&(id1<nv)) { name1=GetVariableName(GetVariable(id1,&(cs->variables))); origID1=GetVariableID(name1,&(cs->orig_variables)); if (origID1==NO_UINT) Error("Undefined ID1 in CSRemoveVarsWithCtRange"); range=GetBoxInterval(origID1,borig); if (IntervalSize(range)==0) { ct2=LowerLimit(range); /* ==UpperLimit(range) */ found=TRUE; } else id1++; } /*if we found something to simplify, apply it to the rest of equations (this creates a new set of equations that replaces the previous one)*/ if (found) { replaced[origID1]=TRUE; AddCt2LinearConstraint(ct2,&(lc[origID1])); #if (_DEBUG>5) printf("Ct Range Replacement: %s [%u-%u] ->%.12g\n",name1,origID1,id1,ct2); #endif if (hold) { TLinearConstraint lc; InitLinearConstraint(&lc); AddCt2LinearConstraint(ct2,&lc); hold=ReplaceVariableInEquations(epsilon,id1,&lc,&(cs->equations)); DeleteLinearConstraint(&lc); RemoveVariable(id1,&(cs->variables)); #if (_DEBUG>6) if(hold) { char **varNames; printf("%%=======================================================\n"); printf("%% One less variable (ct range)\n"); printf("%%****************************************\n"); PrintVariables(stdout,&(cs->variables)); nv=NVariables(&(cs->variables)); NEW(varNames,nv,char *); GetVariableNames(varNames,&(cs->variables)); PrintEquations(stdout,varNames,&(cs->equations)); free(varNames); } #endif } } } while((hold)&&(found)); return(hold); } boolean CSRemoveLCVars(Tparameters *p,unsigned int simplificationLevel, unsigned int nTerms,boolean *changed, boolean *replaced,TLinearConstraint *lc, Tbox *borig,TCuikSystem *cs) { boolean found,hold; unsigned int m,i,j,nv,neq,origID,origID1; Tequation *eq; unsigned int id; char *name,*name1; double epsilon; Tvariable *v; TLinearConstraint lcr,lcc; boolean *systemVars; Tinterval error; Tbox currentBox; boolean polynomial; #if (_DEBUG>5) char **varNamesO; nv=NVariables(&(cs->orig_variables)); NEW(varNamesO,nv,char *); GetVariableNames(varNamesO,&(cs->orig_variables)); #endif polynomial=PolynomialEquations(&(cs->orig_equations)); nv=NVariables(&(cs->variables)); InitBox(nv,NULL,&currentBox); NEW(systemVars,nv,boolean); for(i=0;i<nv;i++) { systemVars[i]=IsSystemVariable(i,&(cs->variables)); SetBoxInterval(i,GetVariableInterval(GetVariable(i,&(cs->variables))),&currentBox); } epsilon=GetParameter(CT_EPSILON,p); *changed=FALSE; hold=TRUE; /* Only scalar equations can be used to generate simplifcation */ found=FALSE; i=0; neq=NScalarEquations(&(cs->equations)); while((!found)&&(i<neq)) { eq=GetScalarEquation(i,&(cs->equations)); found=IsSimplificable(simplificationLevel,nTerms,((cs->scalar)&&(polynomial)), systemVars,&currentBox,&id,&lcr,eq); /* 't' is the type of simplification*/ if (!found) i++; } DeleteBox(&currentBox); /*if we found something to simplify, apply it to the rest of equations (this creates a new set of equations that replaces the previous one)*/ if (found) { *changed=TRUE; /* Translate the variables identifiers from local to global */ v=GetVariable(id,&(cs->variables)); name=GetVariableName(v); origID=GetVariableID(name,&(cs->orig_variables)); if (origID==NO_UINT) Error("Undefined var in original system in CSRemoveLCVars"); /* Translate the 'lcr' linear constraint that refers to the cuiksystem in the current state of simplification to the original system */ m=GetNumTermsInLinearConstraint(&lcr); for(i=0;i<m;i++) { v=GetVariable(GetLinearConstraintVariable(i,&lcr),&(cs->variables)); name1=GetVariableName(v); origID1=GetVariableID(name1,&(cs->orig_variables)); if (origID1==NO_UINT) Error("Undefined variable in original system in CSRemoveLCVars"); AddTerm2LinearConstraint(origID1, GetLinearConstraintCoefficient(i,&lcr), &(lc[origID])); } GetLinearConstraintError(&error,&lcr); if (IntervalSize(&error)>ZERO) Error("Linear constraint used for variable replacement must have ct right-hand"); AddCt2LinearConstraint(-IntervalCenter(&error),&(lc[origID])); replaced[origID]=TRUE; #if (_DEBUG>5) printf("Var Replacement: %s[%u-%u]->",name,origID,id); PrintLinearConstraint(stdout,FALSE,varNamesO,&(lc[origID])); #endif CopyLinearConstraint(&lcc,&(lc[origID])); AddTerm2LinearConstraint(origID,-1.0,&lcc); hold=CropLinearConstraint(ZERO,ANY_TYPE_VAR,borig,&(cs->orig_variables),&lcc); if (!hold) printf("\nNon intersecting ranges (I)\n"); DeleteLinearConstraint(&lcc); /*If origID was used for the replacement of another variable we have to propagate the replacement of origID1 to this other variable*/ nv=NVariables(&(cs->orig_variables)); for(j=0;((hold)&&(j<nv));j++) { if ((replaced[j])&&(LinearConstraintIncludes(origID,&(lc[j])))) { TLinearConstraint ltmp; double ct; ct=RemoveTermFromLinearConstraint(origID,&(lc[j])); CopyLinearConstraint(&ltmp,&(lc[origID])); ScaleLinearConstraint(ct,&ltmp); AddLinearConstraints(&ltmp,&(lc[j])); DeleteLinearConstraint(&ltmp); CopyLinearConstraint(&lcc,&(lc[j])); AddTerm2LinearConstraint(j,-1.0,&lcc); hold=CropLinearConstraint(ZERO,ANY_TYPE_VAR,borig,&(cs->orig_variables),&lcc); if (!hold) printf("\nNon intersecting ranges (II)\n"); DeleteLinearConstraint(&lcc); } } if (hold) { hold=ReplaceVariableInEquations(epsilon,id,&lcr,&(cs->equations)); RemoveVariable(id,&(cs->variables)); #if (_DEBUG>6) if(hold) { char **varNames; printf("%%=======================================================\n"); printf("%% One less variable (replaced)\n"); printf("%%****************************************\n"); PrintVariables(stdout,&(cs->variables)); nv=NVariables(&(cs->variables)); NEW(varNames,nv,char *); GetVariableNames(varNames,&(cs->variables)); PrintEquations(stdout,varNames,&(cs->equations)); free(varNames); } #endif } DeleteLinearConstraint(&lcr); } #if (_DEBUG>5) free(varNamesO); #endif free(systemVars); return(hold); } /* Simplifies a CuikSystem removing variables have constant value and those that depend linearly on other variables. Moreover, a primitive (but numerically save) form of Gaussian elimination is performed to remove as more variables and equations as possible. More elaborate forms of system simplifications are not implemented because they result in numerical errors (that can change the system solutions). The output mappings give information about how the original and the simplified systems are related. This is part of the UpdateCuikSystem. */ boolean SimplifyCuikSystem(Tparameters *p,TCuikSystem *cs) { unsigned int i,nv,nvn,newVarID; boolean *replaced; TLinearConstraint *lc,lcS; boolean changed,anyChange,hold; char *name1; Tbox borig,bsimp; unsigned int nTerms,m,k; Tinterval error; unsigned int simplificationLevel; simplificationLevel=(unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p)); /* Matrix equations or non-polynomial equations -> at most variable replacement */ if ((!cs->scalar)||((!PolynomialEquations(&(cs->orig_equations)))&&(simplificationLevel>1))) simplificationLevel=(simplificationLevel>2?2:simplificationLevel); #if (_DEBUG>6) { char **varNames; printf("%%=======================================================\n"); printf("%% Original system\n"); printf("%%****************************************\n"); PrintVariables(stdout,&(cs->orig_variables)); nv=NVariables(&(cs->orig_variables)); NEW(varNames,nv,char *); GetVariableNames(varNames,&(cs->orig_variables)); PrintEquations(stdout,varNames,&(cs->orig_equations)); free(varNames); } #endif /* Get a copy of the original cuiksystem */ CopyVariables(&(cs->variables),&(cs->orig_variables)); CopyEquations(&(cs->equations),&(cs->orig_equations)); nv=NVariables(&(cs->orig_variables)); /* number of variables in the original system */ NEW(replaced,nv,boolean); NEW(lc,nv,TLinearConstraint); BoxFromVariables(&borig,&(cs->orig_variables)); /*original ranges to be possibly reduced during simplification */ for(i=0;i<nv;i++) { replaced[i]=FALSE; InitLinearConstraint(&(lc[i])); } hold=TRUE; /* in the simplification process we can discover that the input system is inconsitent (i.e., that it does not hold)*/ CSRemoveUnusedVars(p,cs); /* This is done even without simplification */ if (simplificationLevel>0) /* For detailed debug, systems are not simplified */ { hold=CSRemoveVarsWithCtRange(p,replaced,lc,&borig,cs); anyChange=TRUE; /* Set to TRUE to trigger the simplification process */ while((hold)&&(anyChange)) { anyChange=FALSE; /* Will be set to TRUE if at least one variable is removed in the loop below */ nTerms=0; /* First we try to remove ct variables, then scaled ones,i.e., we progressivelly increase the number of terms used in the replacements. */ while((hold)&&(nTerms<=MAX_TERMS_SIMP)) /*hard-coded maximum complexity of the simplifications*/ { hold=CSRemoveLCVars(p,simplificationLevel,nTerms,&changed,replaced,lc,&borig,cs); anyChange=((anyChange)||(changed)); if (changed) nTerms=0; else nTerms++; } /* At this point no more ct or scaled varibles can be removed. Try to simplify the problem via Gaussian elimination*/ if ((hold)&&(anyChange)) { anyChange=FALSE; do { changed=GaussianElimination(&(cs->equations)); anyChange=((anyChange)||(changed)); } while (changed); #if (_DEBUG>6) { char **varNames; unsigned int nvg; printf("%%=======================================================\n"); printf("%% After gaussian elimination\n"); printf("%%****************************************\n"); PrintVariables(stdout,&(cs->variables)); nvg=NVariables(&(cs->variables)); NEW(varNames,nvg,char *); GetVariableNames(varNames,&(cs->variables)); PrintEquations(stdout,varNames,&(cs->equations)); free(varNames); } #endif } } } #if(_DEBUG>4) if (hold) { char **varNames; unsigned int nvg; printf("%%=======================================================\n"); printf("%%FINAL SIMPLIFIED SYSTEM\n"); printf("%%****************************************\n"); PrintVariables(stdout,&(cs->variables)); nvg=NVariables(&(cs->variables)); NEW(varNames,nvg,char *); GetVariableNames(varNames,&(cs->variables)); PrintEquations(stdout,varNames,&(cs->equations)); free(varNames); } else printf("Inconsistent input system\n"); #endif if (hold) { /* Get a copy of the simplified but not still dummified cuiksystem */ CopyVariables(&(cs->simp_variables),&(cs->variables)); CopyEquations(&(cs->simp_equations),&(cs->equations)); /*The final step is to dummify the cuiksystem*/ DummifyCuikSystem(p,cs); /* Cache information in the simplified equations just in case we want to efficiently evalute its equalities. This is done, for instance, in the (cuik)gradient */ CacheScalarEQUInfo(&(cs->simp_equations)); /*define the mappings from the gathered information*/ NEW(cs->orig2sd,1,Tmapping); NEW(cs->orig2s,1,Tmapping); InitMapping(&(cs->orig_variables),&(cs->variables),cs->orig2sd); InitMapping(&(cs->orig_variables),&(cs->simp_variables),cs->orig2s); /* now we complement the default initialization with the replacements computed above */ for(i=0;i<nv;i++) { if (replaced[i]) { m=GetNumTermsInLinearConstraint(&(lc[i])); InitLinearConstraint(&lcS); for(k=0;k<m;k++) { name1=GetVariableName(GetVariable(GetLinearConstraintVariable(k,&(lc[i])),&(cs->orig_variables))); newVarID=GetVariableID(name1,&(cs->variables)); AddTerm2LinearConstraint(newVarID,GetLinearConstraintCoefficient(k,&(lc[i])),&lcS); } GetLinearConstraintError(&error,&(lc[i])); AddCt2LinearConstraint(-IntervalCenter(&error),&lcS); SetOriginalVarRelation(i,&lcS,cs->orig2sd); SetOriginalVarRelation(i,&lcS,cs->orig2s); DeleteLinearConstraint(&lcS); } } #if(_DEBUG>4) if (hold) { char **varNames; unsigned int nvg; printf("%%=======================================================\n"); printf("%%FINAL final SIMPLIFIED SYSTEM\n"); printf("%%****************************************\n"); PrintVariables(stdout,&(cs->variables)); nvg=NVariables(&(cs->variables)); NEW(varNames,nvg,char *); GetVariableNames(varNames,&(cs->variables)); PrintEquations(stdout,varNames,&(cs->equations)); free(varNames); } else printf("Inconsistent input system\n"); #endif SimpleFromOriginal(&borig,&bsimp,cs->orig2s); nvn=NVariables(&(cs->simp_variables)); for(i=0;i<nvn;i++) SetVariableInterval(GetBoxInterval(i,&bsimp),GetVariable(i,&(cs->simp_variables))); DeleteBox(&bsimp); SimpleFromOriginal(&borig,&bsimp,cs->orig2sd); nvn=NVariables(&(cs->variables)); for(i=0;i<nvn;i++) SetVariableInterval(GetBoxInterval(i,&bsimp),GetVariable(i,&(cs->variables))); DeleteBox(&bsimp); } DeleteBox(&borig); /* free the information used for the mapping */ for(i=0;i<nv;i++) DeleteLinearConstraint(&lc[i]); free(replaced); free(lc); return(hold); } /* Removes the information stored in the cuiksystem during the update */ void UnUpdateCuikSystem(TCuikSystem *cs) { if (cs->updated) { /*Removes cached information that is used during solving*/ /*Firt the box sorting information*/ if (cs->searchMode==MINIMIZATION_SEARCH) { DeleteEquation(&(cs->eqMin)); DeleteEquation(&(cs->simp_eqMin)); } /*Now the information about the simplified+dummified system*/ if (cs->orig2sd!=NULL) { DeleteMapping(cs->orig2sd); free(cs->orig2sd); cs->orig2sd=NULL; } cs->nequations=0; cs->nvariables=0; if (cs->systemVar!=NULL) free(cs->systemVar); cs->systemVar=NULL; if (cs->notDummyVar!=NULL) free(cs->notDummyVar); cs->notDummyVar=NULL; if (cs->varType!=NULL) free(cs->varType); cs->varType=NULL; DeleteEquations(&(cs->equations)); DeleteVariables(&(cs->variables)); /*Now remove the information about the simplified system*/ if (cs->orig2s!=NULL) { DeleteMapping(cs->orig2s); free(cs->orig2s); cs->orig2s=NULL; } if (cs->simp_nequations>0) DeleteJacobian(&(cs->J)); cs->simp_nequations=0; cs->simp_nvariables=0;; cs->simp_nee=0; DeleteEquations(&(cs->simp_equations)); DeleteVariables(&(cs->simp_variables)); if (cs->simp_tp!=NULL) free(cs->simp_tp); /*Finally remove the information about the original system*/ cs->orig_nequations=0; cs->orig_nvariables=0; if (cs->orig_systemVar!=NULL) free(cs->orig_systemVar); cs->orig_systemVar=NULL; if (cs->orig_notDummyVar!=NULL) free(cs->orig_notDummyVar); cs->orig_notDummyVar=NULL; free(cs->orig_varNames); cs->orig_varNames=NULL; /*Mark the system as not updated*/ cs->updated=FALSE; /*We assume the system to be consistent although this value is not used unless cs->update is TRUE*/ cs->consistent=TRUE; } } /* Simplifies the CuikSystem and caches information that is useful during solving (cached->faster access). */ boolean UpdateCuikSystem(Tparameters *p,TCuikSystem *cs) { if (!cs->updated) { unsigned int j; boolean found; /* we update even if we have no equations to be able to deal with systems without equations (non constrained problems) In this case cuik is a standard approximated cell decomposition approach */ cs->consistent=SimplifyCuikSystem(p,cs); if (cs->consistent) { /* Update the information in the original system */ cs->orig_nequations=NEquations(&(cs->orig_equations)); cs->orig_nvariables=NVariables(&(cs->orig_variables)); if ((cs->orig_nequations>0)&&(cs->orig_nvariables==0)) Error("System with equations but without variables"); if (cs->orig_nvariables==0) { cs->orig_systemVar=NULL; cs->orig_notDummyVar=NULL; cs->orig_varNames=NULL; } else { NEW(cs->orig_systemVar,cs->orig_nvariables,boolean); NEW(cs->orig_notDummyVar,cs->orig_nvariables,boolean); /* Note that orig_systemVar include the secodary variables while systemVar (the one for the simplified/dummified system) keeps the difference between system and secondary varibles */ for(j=0;j<cs->orig_nvariables;j++) { cs->orig_systemVar[j]=((IsSystemVariable(j,&(cs->orig_variables)))|| (IsSecondaryVariable(j,&(cs->orig_variables)))); cs->orig_notDummyVar[j]=!IsDummyVariable(j,&(cs->orig_variables)); } NEW(cs->orig_varNames,cs->orig_nvariables,char *); GetVariableNames(cs->orig_varNames,&(cs->orig_variables)); } /* Update the simplifed cuiksystem */ cs->simp_nequations=NEquations(&(cs->simp_equations)); cs->simp_nvariables=NVariables(&(cs->simp_variables)); cs->simp_nee=NEqualityEquations(&(cs->simp_equations)); cs->simp_empty=((cs->simp_nvariables==0)&&(cs->simp_nequations==0)); if (cs->simp_empty) cs->simp_tp=NULL; else { GetVariablesTopology(&(cs->simp_tp),&(cs->simp_variables)); found=FALSE; j=0; while ((!found)&&(j<cs->simp_nvariables)) { found=(cs->simp_tp[j]!=TOPOLOGY_R); j++; } if (!found) { free(cs->simp_tp); cs->simp_tp=NULL; } } if (cs->simp_nequations>0) InitJacobian(&(cs->simp_variables),&(cs->simp_equations),&(cs->J)); /* Update the information in the simplified+dummified cuiksystem*/ cs->nequations=NEquations(&(cs->equations)); cs->nvariables=NVariables(&(cs->variables)); cs->empty=((cs->nvariables==0)||(cs->nequations==0)); if (cs->nvariables==0) { cs->systemVar=NULL; cs->notDummyVar=NULL; cs->varType=NULL; } else { NEW(cs->systemVar,cs->nvariables,boolean); NEW(cs->notDummyVar,cs->nvariables,boolean); NEW(cs->varType,cs->nvariables,unsigned int); for(j=0;j<cs->nvariables;j++) { cs->systemVar[j]=IsSystemVariable(j,&(cs->variables)); cs->notDummyVar[j]=!IsDummyVariable(j,&(cs->variables)); cs->varType[j]=GetVariableTypeN(j,&(cs->variables)); } } /* Update the information about the sorting criteria for boxes */ if (cs->searchMode==MINIMIZATION_SEARCH) { if (GetNumMonomials(&(cs->orig_eqMin))==0) { ResetEquation(&(cs->orig_eqMin)); cs->searchMode=DEPTH_FIRST_SEARCH; } else { RewriteEquation2Simp(GetParameter(CT_EPSILON,p), cs->orig2sd,&(cs->eqMin),&(cs->orig_eqMin)); RewriteEquation2Simp(GetParameter(CT_EPSILON,p), cs->orig2s,&(cs->simp_eqMin),&(cs->orig_eqMin)); } } /* Mark the system as updated )(althogh it might not be consistent) */ cs->updated=TRUE; } } return(cs->consistent); } /* Selects one dimension along which to split box 'b'. The dimension can be selected according to the size or according to the error that each variable induce in each equation. The output is a index in the simplified system */ unsigned int ComputeSplitDimInt(Tparameters *p,Tbox *b,TCuikSystem *cs) { if (!UpdateCuikSystem(p,cs)) Error("Inconsistent cuiksystem in ComputeSplitDimInt"); if (cs->nvariables==0) { Error("Splitting an empty cuiksystem"); return(NO_UINT); } else { unsigned int i; Tinterval *is; double *splitDim; unsigned int *d; unsigned int n; double m,s; unsigned int splitType; double epsilon; epsilon=GetParameter(CT_EPSILON,p); splitType=(unsigned int)(GetParameter(CT_SPLIT_TYPE,p)); NEW(splitDim,cs->nvariables,double); NEW(d,cs->nvariables,unsigned int); is=GetBoxIntervals(b); if ((cs->nequations>0)&&(splitType==1)) { for(i=0;i<cs->nvariables;i++) splitDim[i]=0.0; /*Add the error contribution*/ for(i=0;i<cs->nequations;i++) UpdateSplitWeight(i,splitDim,b,&(cs->equations)); /*Do not split along unbounded or too small variables*/ for(i=0;i<cs->nvariables;i++) { s=IntervalSize(&(is[i])); if ((s<10*epsilon)||(s>=INF)) splitDim[i]=0.0; } } else { if (splitType!=2) { /*size-based split or error-based split without any equation*/ for(i=0;i<cs->nvariables;i++) { s=IntervalSize(&(is[i])); if (s<INF) splitDim[i]=s; else splitDim[i]=0.0; } } else { /*splitType==2 -> random selection of the split dimension */ for(i=0;i<cs->nvariables;i++) { s=IntervalSize(&(is[i])); if ((s>10*epsilon)&&(s<INF)) splitDim[i]=1.0; else splitDim[i]=0.0; } } } m=-1.0; n=0; for(i=0;i<cs->nvariables;i++) { if (cs->systemVar[i]) { if (splitDim[i]>m) { m=splitDim[i]; d[0]=i; n=1; } else { if (splitDim[i]==m) { d[n]=i; n++; } } } } if (n>0) { #if (RANDOMNESS) i=d[randomMax(n-1)]; #else i=d[0]; #endif } else { Warning("There is no way where to bisect the box"); i=randomMax(cs->nvariables-1); } free(d); free(splitDim); return(i); } } void SaveCSState(char *fname,Tlist *lb,TCuikSystem *cs) { FILE *f; char *tmpName; double tm; /*We initially save to a temporary file and then we rename it This increases the atomiticy of this operation (if the state file is corrupted the recovery operation would fail) */ NEW(tmpName,strlen(fname)+10,char); sprintf(tmpName,"%s.tmp",fname); /*open in binary mode*/ f=fopen(tmpName,"wb"); if (!f) Error("Could not open file for saving CSState"); tm=GetElapsedTime(&(cs->st)); fwrite(&tm,sizeof(double),1,f); SaveStatistics(f,&(cs->st)); SaveListOfBoxes(f,lb); fclose(f); remove(fname); rename(tmpName,fname); free(tmpName); } void LoadCSState(char *fname,Tlist *lb,TCuikSystem *cs) { FILE *f; double tm; Titerator it; f=fopen(fname,"rb"); if (!f) Error("Could not open file for loading CSState"); fread(&tm,sizeof(double),1,f); LoadStatistics(f,&(cs->st)); LoadListOfBoxes(f,lb); fclose(f); InitIterator(&it,lb); First(&it); if (cs->nvariables!=GetBoxNIntervals((Tbox *)GetCurrent(&it))) Error("The saved .state and the problem dimensionality do not match"); /*Pretend that the process was started tm seconds before now*/ SetInitialTime(GetTime(&(cs->st))-tm,&(cs->st)); } /************************************************************************/ /************************************************************************/ /************************************************************************/ /* Warms up the cuiksystem structure */ void InitCuikSystem(TCuikSystem *cs) { InitConstants(&(cs->constants)); InitVariables(&(cs->orig_variables)); InitEquations(&(cs->orig_equations)); /* cs->variables and cs->equations are initialized via Copy when simplifying the system*/ cs->empty=TRUE; cs->simp_empty=TRUE; cs->updated=FALSE; cs->consistent=TRUE; /*this is not used unless updated=TRUE*/ cs->scalar=TRUE; cs->nequations=0; cs->nvariables=0; cs->systemVar=NULL; cs->notDummyVar=NULL; cs->varType=NULL; cs->orig2sd=NULL; cs->orig2s=NULL; cs->simp_tp=NULL; cs->orig_nequations=0; cs->orig_nvariables=0; cs->orig_systemVar=NULL; cs->orig_notDummyVar=NULL; cs->searchMode=DEPTH_FIRST_SEARCH; InitEquation(&(cs->orig_eqMin)); } void VerifyCuikSystem(Tparameters *p,TCuikSystem *cs) { if (!UpdateCuikSystem(p,cs)) Error("Inconsistent input cuiksystem"); } /* Copies one cuiksystem structure into another (that is assumed as initialized but empty). */ void CopyCuikSystem(TCuikSystem *cs_dst,TCuikSystem *cs_src) { CopyConstants(&(cs_dst->constants),&(cs_src->constants)); cs_dst->updated=cs_src->updated; cs_dst->consistent=cs_src->consistent; cs_dst->empty=cs_src->empty; cs_dst->scalar=cs_src->scalar; CopyStatistics(&(cs_dst->st),&(cs_src->st)); cs_dst->searchMode=cs_src->searchMode; CopyEquation(&(cs_dst->orig_eqMin),&(cs_src->orig_eqMin)); CopyEquations(&(cs_dst->orig_equations),&(cs_src->orig_equations)); CopyVariables(&(cs_dst->orig_variables),&(cs_src->orig_variables)); if (cs_dst->updated) { /*The simplified dummified system*/ NEW(cs_dst->orig2sd,1,Tmapping); CopyMapping(cs_dst->orig2sd,cs_src->orig2sd); CopyEquations(&(cs_dst->equations),&(cs_src->equations)); CopyVariables(&(cs_dst->variables),&(cs_src->variables)); cs_dst->nequations=cs_src->nequations; cs_dst->nvariables=cs_src->nvariables; if (cs_dst->nvariables==0) { cs_dst->systemVar=NULL; cs_dst->notDummyVar=NULL; cs_dst->varType=NULL; } else { NEW(cs_dst->systemVar,cs_dst->nvariables,boolean); memcpy(cs_dst->systemVar,cs_src->systemVar,sizeof(boolean)*cs_dst->nvariables); NEW(cs_dst->notDummyVar,cs_dst->nvariables,boolean); memcpy(cs_dst->notDummyVar,cs_src->notDummyVar,sizeof(boolean)*cs_dst->nvariables); NEW(cs_dst->varType,cs_dst->nvariables,unsigned int); memcpy(cs_dst->varType,cs_src->varType,sizeof(unsigned int)*cs_dst->nvariables); } if (cs_dst->searchMode==MINIMIZATION_SEARCH) { CopyEquation(&(cs_dst->eqMin),&(cs_src->eqMin)); CopyEquation(&(cs_dst->simp_eqMin),&(cs_src->simp_eqMin)); } /*The simplified system*/ NEW(cs_dst->orig2s,1,Tmapping); CopyMapping(cs_dst->orig2s,cs_src->orig2s); cs_dst->simp_empty=cs_src->simp_empty; CopyEquations(&(cs_dst->simp_equations),&(cs_src->simp_equations)); CopyVariables(&(cs_dst->simp_variables),&(cs_src->simp_variables)); cs_dst->simp_nequations=cs_src->simp_nequations; cs_dst->simp_nvariables=cs_src->simp_nvariables; cs_dst->simp_nee=cs_src->simp_nee; if (cs_src->simp_tp!=NULL) { NEW(cs_dst->simp_tp,cs_dst->simp_nvariables,unsigned int); memcpy(cs_dst->simp_tp,cs_src->simp_tp,sizeof(unsigned int)*cs_dst->simp_nvariables); } else cs_dst->simp_tp=NULL; CopyJacobian(&(cs_dst->J),&(cs_src->J)); /*Cached elements from the original system*/ cs_dst->orig_nequations=cs_src->orig_nequations; cs_dst->orig_nvariables=cs_src->orig_nvariables; if (cs_dst->orig_nvariables==0) { cs_dst->orig_systemVar=NULL; cs_dst->orig_notDummyVar=NULL; cs_dst->orig_varNames=NULL; } else { NEW(cs_dst->orig_systemVar,cs_dst->orig_nvariables,boolean); memcpy(cs_dst->orig_systemVar,cs_src->orig_systemVar,cs_dst->orig_nvariables*sizeof(boolean)); NEW(cs_dst->orig_notDummyVar,cs_dst->orig_nvariables,boolean); memcpy(cs_dst->orig_notDummyVar,cs_src->orig_notDummyVar,cs_dst->orig_nvariables*sizeof(boolean)); NEW(cs_dst->orig_varNames,cs_dst->orig_nvariables,char *); GetVariableNames(cs_dst->orig_varNames,&(cs_dst->orig_variables)); } } else { cs_dst->orig2sd=NULL; cs_dst->orig2s=NULL; cs_dst->nequations=0; cs_dst->nvariables=0; cs_dst->systemVar=NULL; cs_dst->notDummyVar=NULL; cs_dst->varType=NULL; cs_dst->simp_tp=NULL; cs_dst->orig_nequations=0; cs_dst->orig_nvariables=0; cs_dst->orig_systemVar=NULL; cs_dst->orig_notDummyVar=NULL; cs_dst->orig_varNames=NULL; } } void CuikSystemMerge(Tparameters *p,TCuikSystem *cs1,TCuikSystem *cs2,TCuikSystem *cs) { unsigned int nvar1,nvar2; unsigned int i; InitCuikSystem(cs); MergeConstants(&(cs1->constants),&(cs2->constants),&(cs->constants)); cs->empty=((cs1->empty)&&(cs2->empty)); cs->simp_empty=((cs1->simp_empty)&&(cs2->simp_empty)); cs->updated=FALSE; cs->consistent=TRUE; /*not used untill updated==TRUE*/ cs->scalar=((ScalarEquations(&(cs1->orig_equations)))&& (ScalarEquations(&(cs->orig_equations)))); cs->orig2sd=NULL; cs->nequations=0; cs->nvariables=0; cs->systemVar=NULL; cs->notDummyVar=NULL; cs->varType=NULL; cs->orig_nequations=0; cs->orig_nvariables=0; cs->orig_systemVar=NULL; cs->orig_notDummyVar=NULL; /* One of the sets of variables is supposed to be a sub-set of the other. If nvar1 is larger than the larger set was in cs1 and nothing has to be done*/ CopyVariables(&(cs->orig_variables),&(cs1->orig_variables)); nvar1=NVariables(&(cs1->orig_variables)); nvar2=NVariables(&(cs2->orig_variables)); for(i=nvar1;i<nvar2;i++) AddVariable2CS(GetVariable(i,&(cs2->orig_variables)),cs); CopyEquations(&(cs->orig_equations),&(cs1->orig_equations)); MergeEquations(&(cs2->orig_equations),&(cs->orig_equations)); cs->searchMode=cs1->searchMode; CopyEquation(&(cs->orig_eqMin),&(cs1->orig_eqMin)); AccumulateEquations(&(cs2->orig_eqMin),1,&(cs->orig_eqMin)); } double EvaluateEqMin(void *b,void *cs) { double v=0; if (!((TCuikSystem *)cs)->updated) Error("The CuikSystem must be updated before using EvaluateEqMin"); if (!((TCuikSystem *)cs)->consistent) Error("The CuikSystem must be consistent before using EvaluateEqMin"); if (((TCuikSystem *)cs)->searchMode==MINIMIZATION_SEARCH) { #if (EQ_MIN_IN_CENTER) unsigned int nv; double *p; unsigned int i; nv=NVariables(&(((TCuikSystem *)cs)->variables)); NEW(p,nv,double); for(i=0;i<nv;i++) p[i]=IntervalCenter(GetBoxInterval(i,(Tbox *)b)); v=EvaluateWholeEquation(p,&(((TCuikSystem *)cs)->eqMin)); free(p); #else Tinterval ie; double ct; ct=GetEquationValue(&(((TCuikSystem *)cs)->eqMin)); EvaluateEquationInt(GetBoxIntervals((Tbox *)b),&ie,&(((TCuikSystem *)cs)->eqMin)); IntervalOffset(&ie,-ct,&ie); /*v=LowerLimit(&ie);*/ /*v=UpperLimit(&ie);*/ v=IntervalCenter(&ie); #endif } return(v); } boolean CmpBoxesEquation(void *b1,void *b2,void *cs) { return(EvaluateEqMin(b1,cs)<EvaluateEqMin(b2,cs)); } void SetCSSearchMode(unsigned int sm,Tequation *eqMin,TCuikSystem *cs) { if (cs->updated) UnUpdateCuikSystem(cs); switch(sm) { case DEPTH_FIRST_SEARCH: cs->searchMode=DEPTH_FIRST_SEARCH; break; case BREADTH_FIRST_SEARCH: cs->searchMode=BREADTH_FIRST_SEARCH; break; case MINIMIZATION_SEARCH: cs->searchMode=MINIMIZATION_SEARCH; DeleteEquation(&(cs->orig_eqMin)); CopyEquation(&(cs->orig_eqMin),eqMin); break; default: Error("Unkonwn search mode in SetCSSearchMode"); } } void AddTerm2SearchCriterion(double w,unsigned int v,double val,TCuikSystem *cs) { if (w!=0.0) { Tequation eq; Tmonomial m; if (cs->updated) UnUpdateCuikSystem(cs); InitEquation(&eq); SetEquationCmp(EQU,&eq); InitMonomial(&m); AddCt2Monomial(w,&m); AddVariable2Monomial(NFUN,v,2,&m); AddMonomial(&m,&eq); ResetMonomial(&m); AddCt2Monomial(-w*2*val,&m); AddVariable2Monomial(NFUN,v,1,&m); AddMonomial(&m,&eq); ResetMonomial(&m); AddCt2Monomial(w*val*val,&m); AddMonomial(&m,&eq); ResetMonomial(&m); if (cs->searchMode==MINIMIZATION_SEARCH) AccumulateEquations(&eq,1,&(cs->orig_eqMin)); else SetCSSearchMode(MINIMIZATION_SEARCH,&eq,cs); DeleteMonomial(&m); DeleteEquation(&eq); } } /* Adds a equation to the CuikSystem. Equations as added by the user are not dummified. This helps when simplifying the system (dummify variables can prevent some simplifications or make them more "obscure") The dummificitaion is applied after the simplification of the system (see SimplifyCuikSystem) */ void AddEquation2CS(Tparameters *p,Tequation *eq,TCuikSystem *cs) { if (cs->updated) UnUpdateCuikSystem(cs); if (eq!=NULL) AddEquation(eq,&(cs->orig_equations)); } void AddMatrixEquation2CS(Tparameters *p,TMequation *eq,TCuikSystem *cs) { if (cs->updated) UnUpdateCuikSystem(cs); if (eq!=NULL) { cs->scalar=FALSE; if (!SimplifiedMEquation(eq)) Error("Adding a non-simplified matrix equation to the cuiksystem"); //SimplifyMEquation(eq); AddMatrixEquation(eq,&(cs->orig_equations)); } } /* Checks if the system has a variable with the given name. If so, we return the variable identifier. If not, we create a new variable */ unsigned int AddVariable2CS(Tvariable *v,TCuikSystem *cs) { unsigned int id; if (cs->updated) UnUpdateCuikSystem(cs); id=GetVariableID(GetVariableName(v),&(cs->orig_variables)); if (id==NO_UINT) id=AddVariable(v,&(cs->orig_variables)); return(id); } /* Returns a copy of the variables stored in the CuikSystem */ void GetCSVariables(Tvariables *vs,TCuikSystem *cs) { CopyVariables(vs,&(cs->orig_variables)); } void GetCSVariableNames(char **varNames,TCuikSystem *cs) { /* We do not use the cached orig_varnames since the cs can be non-updated */ GetVariableNames(varNames,&(cs->orig_variables)); } /* Returns the number of variables in the CuikSystem */ unsigned int GetCSNumVariables(TCuikSystem *cs) { return(NVariables(&(cs->orig_variables))); } unsigned int GetCSNumSystemVariables(TCuikSystem *cs) { return(GetNumSystemVariables(&(cs->orig_variables))+ GetNumSecondaryVariables(&(cs->orig_variables))); } /* Returns the number of system variables in the CuikSystem */ unsigned int GetCSNumNonDummyVariables(TCuikSystem *cs) { return(NVariables(&(cs->orig_variables))-GetNumDummyVariables(&(cs->orig_variables))); } /* Gets a copy of variable with ID 'n' */ void GetCSVariable(unsigned int n,Tvariable *v,TCuikSystem *cs) { CopyVariable(v,GetVariable(n,&(cs->orig_variables))); } /* Sets a new range for variable with ID 'n' */ void SetCSVariableRange(unsigned int n,Tinterval *r,TCuikSystem *cs) { if (cs->updated) UnUpdateCuikSystem(cs); /* Variables with ct range are simplified in the UpdateCuikSystem */ SetVariableInterval(r,GetVariable(n,&(cs->orig_variables))); } /* Gets the ID of the variable with the given name */ unsigned int GetCSVariableID(char *name,TCuikSystem *cs) { return(GetVariableID(name,&(cs->orig_variables))); } char *GetCSVariableName(unsigned int id,TCuikSystem *cs) { return(VariableName(id,&(cs->orig_variables))); } char *GetCSSystemVariableName(unsigned int id,TCuikSystem *cs) { unsigned int i,n,k; boolean found; char *name=NULL; n=NVariables(&(cs->orig_variables)); k=0; found=FALSE; for(i=0;((!found)&&(i<n));i++) if ((IsSystemVariable(i,&(cs->orig_variables)))|| (IsSecondaryVariable(i,&(cs->orig_variables)))) { if (k==id) { name=VariableName(i,&(cs->orig_variables)); found=TRUE; } k++; } return(name); } boolean IsSystemVarInSimpCS(Tparameters *p,char *v,TCuikSystem *cs) { unsigned int n; if (!UpdateCuikSystem(p,cs)) Error("Inconsistent input cuiksystem"); n=GetVariableID(v,&(cs->simp_variables)); return((n!=NO_UINT)&& ((IsSystemVariable(n,&(cs->simp_variables)))|| (IsSecondaryVariable(n,&(cs->simp_variables))))); } /* Returns an array of booleans with sv[i]=TRUE if variable 'i' is a system variable. Also returns the number of variables in the CuikSystem */ unsigned int GetCSSystemVars(boolean **sv,TCuikSystem *cs) { unsigned int i,n; n=NVariables(&(cs->orig_variables)); NEW(*sv,n,boolean); for(i=0;i<n;i++) (*sv)[i]=((IsSystemVariable(i,&(cs->orig_variables)))|| (IsSecondaryVariable(i,&(cs->orig_variables)))); return(n); } unsigned int GetCSVarTopology(unsigned int vID,TCuikSystem *cs) { return(GetVariableTopology(GetVariable(vID,&(cs->orig_variables)))); } /* Returns a copy of the equations in the cuiksystem */ void GetCSEquations(Tequations *eqs,TCuikSystem *cs) { CopyEquations(eqs,&(cs->orig_equations)); } /* Returns a copy of equation 'n' in the CuikSystem */ void GetCSEquation(unsigned int n,Tequation *eq,TCuikSystem *cs) { if (!cs->scalar) Error("GetCSEquation only operates on scalar systems"); CopyEquation(eq,GetEquation(n,&(cs->orig_equations))); } boolean IsCSPolynomial(TCuikSystem *cs) { return(PolynomialEquations(&(cs->orig_equations))); } boolean IsCSScalar(TCuikSystem *cs) { return(cs->scalar); } /* Returns the number of equations in the CuikSytem */ unsigned int GetCSNumEquations(TCuikSystem *cs) { return(NEquations(&(cs->orig_equations))); } void GetCSJacobian(TJacobian *J,TCuikSystem *cs) { InitJacobian(&(cs->orig_variables),&(cs->orig_equations),J); } unsigned int GetSimpCSTopology(Tparameters *p, unsigned int **t,TCuikSystem *cs) { if (!UpdateCuikSystem(p,cs)) Error("Inconsistent input cuiksystem"); return(GetVariablesTopology(t,&(cs->simp_variables))); } unsigned int GetCSTopology(Tparameters *p, unsigned int **t,TCuikSystem *cs) { return(GetVariablesTopology(t,&(cs->orig_variables))); } void GetSimpCSJacobian(Tparameters *p,TJacobian *J,TCuikSystem *cs) { if (!UpdateCuikSystem(p,cs)) Error("Inconsistent input cuiksystem"); InitJacobian(&(cs->simp_variables),&(cs->simp_equations),J); } void AddJacobianEquationsInt(Tparameters *p,boolean *selectedVars,TJacobian *J, TCuikSystem *cs) { Tinterval one_one,zero_one; unsigned int *nvl; Tvariable v; char vname[100]; Tequation eq,eq1; unsigned int i,j,nvars,neqs; if (!cs->scalar) Error("AddJacobianEquationsInt only operates on scalar systems"); GetJacobianSize(&neqs,&nvars,J); NewInterval(-1.0,1.0,&one_one); NewInterval( 0.0,1.0,&zero_one); /* From this point we start to modify cs and thus, all queries to the original cs must be done on csOrig*/ /*define the lambda variables*/ NEW(nvl,neqs,unsigned int); for(i=0;i<neqs;i++) { sprintf(vname,"_lambda_%u",i); NewVariable(SYSTEM_VAR,vname,&v); SetVariableInterval((i==0?&zero_one:&one_one),&v); nvl[i]=AddVariable2CS(&v,cs); DeleteVariable(&v); } /*Lambdas must be normalized*/ GenerateGeneralNormEquation(neqs,nvl,1.0,&eq); AddEquation2CS(p,&eq,cs); DeleteEquation(&eq); /*define the linear combination using the lambda*/ for(j=0;j<nvars;j++) { if ((selectedVars==NULL)||(selectedVars[j])) { InitEquation(&eq); SetEquationCmp(EQU,&eq); SetEquationType(SYSTEM_EQ,&eq); for(i=0;i<neqs;i++) { CopyEquation(&eq1,GetJacobianEquation(i,j,J)); VarScaleEquation(nvl[i],&eq1); AccumulateEquations(&eq1,1.0,&eq); DeleteEquation(&eq1); } AddEquation2CS(p,&eq,cs); DeleteEquation(&eq); } } } void AddJacobianEquations(Tparameters *p,boolean *selectedVars,TCuikSystem *cs) { unsigned int neqs,nvars,i,ns; TCuikSystem csOrig; TJacobian J; if (!UpdateCuikSystem(p,cs)) Error("Inconsistent input cuiksystem"); CopyCuikSystem(&csOrig,cs); GetCSJacobian(&J,&csOrig); GetJacobianSize(&neqs,&nvars,&J); if (selectedVars==NULL) ns=nvars; else { ns=0; for(i=0;i<nvars;i++) if (selectedVars[i]) ns++; } if ((neqs>0)&&(ns>0)) AddJacobianEquationsInt(p,selectedVars,&J,cs); DeleteJacobian(&J); UnUpdateCuikSystem(cs); DeleteCuikSystem(&csOrig); } void AddSimplifiedJacobianEquations(Tparameters *p,boolean *selectedVars,TCuikSystem *cs) { unsigned int neqs,nvars,i,ns; boolean *simpSelectedVars; unsigned int simpID,nt; TLinearConstraint lc; TCuikSystem csOrig; if (!cs->scalar) Error("AddSimplifiedJacobianEquations only operates on scalar systems"); if (!UpdateCuikSystem(p,cs)) Error("Inconsistent input cuiksystem"); CopyCuikSystem(&csOrig,cs); neqs=cs->simp_nee; nvars=cs->simp_nvariables; NEW(simpSelectedVars,nvars,boolean); if (selectedVars==NULL) ns=nvars; else { /*Translated the selected vars from original to simplified*/ for(i=0;i<nvars;i++) simpSelectedVars[i]=TRUE; ns=0; for(i=0;i<cs->orig_nvariables;i++) { if (!selectedVars[i]) { GetOriginalVarRelation(i,&lc,cs->orig2s); nt=GetNumTermsInLinearConstraint(&lc); /* if nt is zero the variable is set to constant and must be not taken into account*/ if (nt>0) { ns++; /*We use the first variable in the simplified system as equivalent to the original variable*/ simpID=GetLinearConstraintVariable(0,&lc); simpSelectedVars[simpID]=FALSE; #if (_DEBUG>0) printf(" Var %s -> %s\n",cs->orig_varNames[i], VariableName(simpID,&(cs->simp_variables))); #endif } #if (_DEBUG>0) else printf(" Var %s -> constant (not considered)\n",cs->orig_varNames[i]); #endif DeleteLinearConstraint(&lc); } } } if ((neqs>0)&&(ns>0)) { TJacobian J; Tequation *eq; unsigned int j; /* We have to translate the simplified Jacobian matrix to the original system */ InitJacobian(&(csOrig.simp_variables),&(csOrig.simp_equations),&J); for(i=0;i<neqs;i++) { for(j=0;j<nvars;j++) { eq=GetJacobianEquation(i,j,&J); RewriteEquation2Orig(csOrig.orig2s,eq,eq); } } #if (_DEBUG>1) { char **varNames; NEW(varNames,csOrig.orig_nvariables,char*); GetVariableNames(varNames,&(csOrig.orig_variables)); for(j=0;j<nvars;j++) { for(i=0;i<neqs;i++) { printf("J[%u,%u] ->",i,j); PrintEquation(stdout,varNames,GetJacobianEquation(i,j,&J)); } } free(varNames); } #endif AddJacobianEquationsInt(p,simpSelectedVars,&J,cs); DeleteJacobian(&J); } UnUpdateCuikSystem(cs); DeleteCuikSystem(&csOrig); } /* Reduces a box as much as possible (according to parameters in 'p'). If the set of parameters is undefined, we use a default set. This procedure is used in CuikPlan. This is basically another flavor of ReduceBox where parameters are given in one structure instead of as different inputs The input box and output boxes are refered to the original cuiksystem (the non-simplified one) The output can be EMPTY_BOX REDUCED_BOX REDUCED_BOX_WITH_SOLUTION ERROR_IN_PROCESS */ unsigned int MaxReduction(Tparameters *p,unsigned int varMask,double *reduction,Tbox *b,TCuikSystem *cs) { unsigned int e; if (!cs->scalar) Error("MaxReduction only operates on scalar systems"); if (UpdateCuikSystem(p,cs)) { Tbox bsimp; double sIn,sOut; SimpleFromOriginal(b,&bsimp,cs->orig2sd); sIn=GetBoxSize(cs->systemVar,&bsimp); e=ReduceBox(p,(varMask==0?~DUMMY_VAR:varMask),&bsimp,cs); if (e==EMPTY_BOX) *reduction=0; else { sOut=GetBoxSize(cs->systemVar,&bsimp); *reduction=sOut/sIn; /* ERROR_IN_PROCESS, REDUCED_BOX, REDUCED_BOX_WITH_SOLUTION*/ UpdateOriginalFromSimple(&bsimp,b,cs->orig2sd); } DeleteBox(&bsimp); } else e=EMPTY_BOX; return(e); } boolean SampleCuikSystem(Tparameters *p,char *fname,Tlist *sb, unsigned int nsamples,unsigned int ntries, unsigned int ndof,TCuikSystem *cs) { Tbox init_box; boolean haveSample; if (!cs->scalar) Error("SampleCuikSystem only operates on scalar systems"); GenerateInitialBox(&init_box,cs); haveSample=SampleCuikSystemInBox(p,fname,sb,nsamples,ntries,ndof,&init_box,cs); DeleteBox(&init_box); return(haveSample); } boolean SampleCuikSystemInBox(Tparameters *p,char *fname,Tlist *sb, unsigned int nsamples,unsigned int ntries, unsigned int ndof, Tbox *init_box,TCuikSystem *cs) { Tbox orig_ranges,b,*bAux,*box; Tlist solutions; unsigned int k,d,ns,nv,ne,i,nt; double v; Tfilename fsols_box; Tfilename fsols_point; FILE *f_out_box; FILE *f_out_point; Titerator it; boolean *systemVars; Tinterval *r; unsigned int spt; double ms; double reduction; boolean ok; boolean end; /* free var = variable not in equations -> must be fixed always */ unsigned int *freeVars; unsigned int nFreeVars; unsigned int nsols; if (!cs->scalar) Error("SampleCuikSystemInBox only operates on scalar systems"); /*Get a copy of the ranges in 'cs' for all the variables*/ GenerateInitialBox(&orig_ranges,cs); /*Set the ranges for the 'cs' variables to those in the given box (init_box)*/ if (cs->updated) UnUpdateCuikSystem(cs); nv=NVariables(&(cs->orig_variables)); for(k=0;k<nv;k++) SetVariableInterval(GetBoxInterval(k,init_box),GetVariable(k,&(cs->orig_variables))); NEW(freeVars,nv,unsigned int); nFreeVars=0; for(k=0;k<nv;k++) { if ((GetVariableTypeN(k,&(cs->orig_variables))==SYSTEM_VAR)&& (!UsedVarInEquations(k,&(cs->orig_equations)))) { freeVars[nFreeVars]=k; nFreeVars++; } } /*Change the SPLIT_TYPE parameter to random split*/ spt=(unsigned int)GetParameter(CT_SPLIT_TYPE,p); ChangeParameter(CT_SPLIT_TYPE,2,p); /* select split dimentions at random */ /*Change the SMALL_SIGMA parameter to ensure it is small enough. SMALL_SIGMA controls the precission of the isolated solutions and, thus, of the sampled points. */ ms=GetParameter(CT_SMALL_SIGMA,p); ChangeParameter(CT_SMALL_SIGMA,100*GetParameter(CT_EPSILON,p),p); /*keep the original nsols parameter*/ nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p); if (fname==NULL) { f_out_box=NULL; f_out_point=NULL; } else { /* Check if we can create the output files */ CreateFileName(NULL,fname,"_samples",SOL_EXT,&fsols_box); f_out_box=fopen(GetFileFullName(&fsols_box),"w"); if (!f_out_box) Error("Could not open box sample output file"); CreateFileName(NULL,fname,NULL,LINKS_EXT,&fsols_point); f_out_point=fopen(GetFileFullName(&fsols_point),"w"); if (!f_out_point) Error("Could not open box sample output file"); } if (sb!=NULL) InitListOfBoxes(sb); nv=GetCSNumVariables(cs); ne=GetCSNumEquations(cs); if (ndof==NO_UINT) { /* try to get the number of dof from the system (vars-equations) */ if (ne>=nv) Error("Over/Well-constrained system. Please indicate the number of dof in the call"); ndof=nv-ne; } if (MaxReduction(p,~DUMMY_VAR,&reduction,init_box,cs)==EMPTY_BOX) end=TRUE; else end=FALSE; if (nFreeVars>ndof) Error("More free vars than degrees of freedom"); ns=0; /*samples already determined*/ nt=0; /*number of tries so far*/ while(!end) { do { ok=TRUE; /*fix 'ndof' variables*/ CopyBox(&b,init_box); for(k=0;k<nv;k++) SetCSVariableRange(k,GetBoxInterval(k,&b),cs); for(k=0;k<nFreeVars;k++) { r=GetBoxInterval(freeVars[k],&b); v=randomInInterval(r); #if (_DEBUG>1) printf("[CS]->fixing %u to %f\n",freeVars[k],v); #endif NewInterval(v,v,r); SetCSVariableRange(freeVars[k],r,cs); } for(k=nFreeVars;((ok)&&(k<ndof));k++) { /*fix 'ndof' variables*/ /* This updates the system, including simplification */ d=ComputeSplitDim(p,&b,cs); if (d==NO_UINT) ok=FALSE; else { r=GetBoxInterval(d,&b); v=randomInInterval(r); #if (_DEBUG>1) printf("[CS]->fixing %u to %f\n",d,v); #endif NewInterval(v,v,r); SetCSVariableRange(d,r,cs); } } #if (_DEBUG>1) if (ok) {printf("[CS]");PrintBox(stdout,&b);} else printf("Inconsistent system while sampling\n"); #endif DeleteBox(&b); nt++; if ((ntries!=NO_UINT)&&(nt==ntries)) end=TRUE; } while((!ok)&&(!end)); if (!end) { /**/ InitListOfBoxes(&solutions); /*See if there are solutions for the fixed ranges*/ ChangeParameter(CT_N_SOLUTIONS,nsamples-ns,p); SolveCuikSystem(p,FALSE,NULL,NULL,f_out_box,&solutions,cs); /*We have to print the samples*/ GetCSSystemVars(&systemVars,cs); InitIterator(&it,&solutions); First(&it); while((!EndOfList(&it))&&(!end)) { bAux=(Tbox *)GetCurrent(&it); if (f_out_point!=NULL) { /* Print the center of the box into the point file */ /* We only print values for the system vars */ for(i=0;i<nv;i++) { if (systemVars[i]) fprintf(f_out_point," %.12g",IntervalCenter(GetBoxInterval(i,bAux))); } fprintf(f_out_point,"\n"); } if (sb!=NULL) { NEW(box,1,Tbox); CopyBox(box,bAux); AddLastElement((void *)box,sb); } ns++; if (ns<nsamples) end=TRUE; Advance(&it); } free(systemVars); fflush(f_out_point); fflush(f_out_box); /*Remove all boxes from the list and the current box*/ DeleteListOfBoxes(&solutions); } } if (f_out_box!=NULL) { DeleteFileName(&fsols_box); fclose(f_out_box); } if (f_out_point!=NULL) { fclose(f_out_point); DeleteFileName(&fsols_point); } /*Restore the user given split_type, min_sigma, and n_solutions*/ ChangeParameter(CT_SPLIT_TYPE,spt,p); ChangeParameter(CT_SMALL_SIGMA,ms,p); ChangeParameter(CT_N_SOLUTIONS,nsols,p); /*Return the original ranges to the 'cs' variables*/ if (cs->updated) UnUpdateCuikSystem(cs); nv=NVariables(&(cs->orig_variables)); for(k=0;k<nv;k++) SetVariableInterval(GetBoxInterval(k,&orig_ranges),GetVariable(k,&(cs->orig_variables))); free(freeVars); DeleteBox(&orig_ranges); return(!end); } boolean IncrementalSampleCuikSystem(Tparameters *p,char *fname,Tlist *sb, boolean *fixVars, unsigned int nsamples,unsigned int ntries, unsigned int ndof,TCuikSystem *cs) { Tbox init_box; boolean haveSample; if (!cs->scalar) Error("IncrementalSampleCuikSystem only operates on scalar systems"); GenerateInitialBox(&init_box,cs); haveSample=IncrementalSampleCuikSystemInBox(p,fname,sb,fixVars,nsamples,ntries,ndof,&init_box,cs); DeleteBox(&init_box); return(haveSample); } boolean IncrementalSampleCuikSystemInBox(Tparameters *p,char *fname,Tlist *sb, boolean *fixVars, unsigned int nsamples,unsigned int ntries, unsigned int ndof, Tbox *init_box,TCuikSystem *cs) { Tbox b,*bAux,*box; Tlist solutions; unsigned int k,d,ns,nv,ne,i,nt; double v; double smallSigma; Tfilename fsols_box; Tfilename fsols_point; FILE *f_out_box; FILE *f_out_point; Titerator it; boolean *systemVars; Tinterval *r,newr; Tbox *bl; double ms; double reduction; boolean ok; boolean end; boolean *fv; unsigned int *ind2fv; unsigned int nfv; unsigned int newtonIterations; double *sol; Tbox b_sol; Tbox orig_ranges; unsigned int level,*attempts,maxAttemptsPerLevel; unsigned int nsols; if (!cs->scalar) Error("IncrementalSampleCuikSystemInBox only operates on scalar systems"); /*Set the ranges for the 'cs' variables to those in the given box (init_box)*/ if (!UpdateCuikSystem(p,cs)) Error("Inconsistent cuiksystem in IncrementalSampleCuikSystemInBox"); BoxFromVariables(&orig_ranges,&(cs->orig_variables)); nv=NVariables(&(cs->orig_variables)); NEW(sol,nv,double); ms=GetParameter(CT_SMALL_SIGMA,p); smallSigma=100*GetParameter(CT_EPSILON,p); ChangeParameter(CT_SMALL_SIGMA,smallSigma,p); nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p); newtonIterations=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p); /* Array of variables that can be fixed */ NEW(fv,nv,boolean); NEW(ind2fv,nv,unsigned int); nfv=0; for(k=0;k<nv;k++) { if ((IntervalSize(GetBoxInterval(k,init_box))>smallSigma)&& (IsInSimple(k,cs->orig2sd))) { if (((fixVars!=NULL)&&(fixVars[k]))|| ((fixVars==NULL)&&(IsSystemVariable(k,&(cs->orig_variables))))) { fv[k]=TRUE; ind2fv[nfv]=k; nfv++; } else fv[k]=FALSE; } else fv[k]=FALSE; } if (fname==NULL) { f_out_box=NULL; f_out_point=NULL; } else { /* Check if we can create the output files */ CreateFileName(NULL,fname,"_samples",SOL_EXT,&fsols_box); f_out_box=fopen(GetFileFullName(&fsols_box),"w"); if (!f_out_box) Error("Could not open box sample output file"); CreateFileName(NULL,fname,NULL,LINKS_EXT,&fsols_point); f_out_point=fopen(GetFileFullName(&fsols_point),"w"); if (!f_out_point) Error("Could not open box sample output file"); } if (sb!=NULL) InitListOfBoxes(sb); nv=GetCSNumVariables(cs); ne=GetCSNumEquations(cs); if (ndof==NO_UINT) { /* try to get the number of dof from the system (vars-equations) */ if (ne>=nv) Error("Over/Well-constrained system. Please indicate the number of dof in the call"); ndof=nv-ne; } #if (_DEBUG>1) printf("Initial reduction (s:%g)\n",GetBoxSumSide(NULL,init_box)); #endif if (MaxReduction(p,~DUMMY_VAR,&reduction,init_box,cs)==EMPTY_BOX) end=TRUE; else end=FALSE; #if (_DEBUG>1) if (!end) { printf("[CS] (s:%g)",GetBoxSumSide(NULL,init_box)); PrintBox(stdout,init_box); } else printf("Inconsistent system while sampling\n"); fflush(stdout); #endif NEW(attempts,ndof,unsigned int); NEW(bl,ndof,Tbox); maxAttemptsPerLevel=10; ns=0; /*samples already determined*/ nt=0; /*time we tried to sample so far*/ while((!end)&&(ns<nsamples)) { ok=TRUE; CopyBox(&b,init_box); /*fix ndof variables*/ level=0; for(k=0;k<ndof;k++) attempts[k]=0; while((level<ndof)&&(!end)) { /*Keep a copy of the box BEFORE fixing the new variable at the current 'level'. This is used when backtracking to recover the state before this assigment*/ CopyBox(&(bl[level]),&b); do { /*select one of the still not fixed variables*/ d=ind2fv[randomMax(nfv-1)]; r=GetBoxInterval(d,&b); } while (IntervalSize(r)<=smallSigma); #if (_DEBUG>1) printf("[CS](level %u/%u bs:%f)",level,ndof,GetBoxSumSide(NULL,&b)); #endif { Tinterval raux; double c,l; c=IntervalCenter(r); l=IntervalSize(r)/2; NewInterval(c-l,c+l,&raux); /*Now change the current box ,b*/ v=randomInInterval(&raux); } //v=randomInInterval(r); NewInterval(v,v,&newr); SetBoxInterval(d,&newr,&b); /* Change the variable ranges to those in b */ UnUpdateCuikSystem(cs); VariablesFromBox(&b,&(cs->orig_variables)); attempts[level]++; #if (_DEBUG>1) printf("(attempts %u/%u)->fixing %u to %f \n", attempts[level],maxAttemptsPerLevel,d,v); #endif /* And reduce the systems as much as possible */ ok=((UpdateCuikSystem(p,cs))&& (MaxReduction(p,~DUMMY_VAR,&reduction,&b,cs)!=EMPTY_BOX)); if (ok) { if (newtonIterations>0) { if ((CuikNewtonInBox(p,&b,sol,&b_sol,cs)&(CONVERGED_IN_GLOBAL|CONVERGED_IN_BOX))>0) { fprintf(f_out_box,"Newton (%g)",ErrorInSolution(&b_sol,cs)); PrintBoxSubset(f_out_box,cs->orig_notDummyVar,cs->orig_varNames,&b_sol); fflush(f_out_box); } DeleteBox(&b_sol); } level++; #if (_DEBUG>1) printf("[CS] (l:%u s:%g)",level,GetBoxSumSide(NULL,&b)); PrintBox(stdout,&b); #endif } else { #if (_DEBUG>1) printf("Inconsistent system while sampling. Backtracking\n"); #endif /*Undo the last assigment*/ DeleteBox(&b); CopyBox(&b,&(bl[level])); DeleteBox(&(bl[level])); if (attempts[level]>maxAttemptsPerLevel) { attempts[level]=0; if (level>0) { level--; /*move to the state just before the assigment at leve-1*/ DeleteBox(&b); CopyBox(&b,&(bl[level])); DeleteBox(&(bl[level])); } } } } if (ok) { /* Last degree of freedom is not fixed but we solve the cuiksystem in the box */ InitListOfBoxes(&solutions); /*See if there are solutions for the fixed ranges*/ ChangeParameter(CT_N_SOLUTIONS,nsamples-ns,p); SolveCuikSystem(p,FALSE,NULL,&b,f_out_box,&solutions,cs); /*We have to print the samples*/ GetCSSystemVars(&systemVars,cs); InitIterator(&it,&solutions); First(&it); while((!EndOfList(&it))&&(ns<nsamples)) { bAux=(Tbox *)GetCurrent(&it); if (f_out_point!=NULL) { /* Print the center of the box into the point file */ /* We only print values for the system vars */ for(i=0;i<nv;i++) { if (systemVars[i]) fprintf(f_out_point," %.12g",IntervalCenter(GetBoxInterval(i,bAux))); } fprintf(f_out_point,"\n"); } if (sb!=NULL) { NEW(box,1,Tbox); CopyBox(box,bAux); AddLastElement((void *)box,sb); } ns++; Advance(&it); } free(systemVars); fflush(f_out_point); fflush(f_out_box); /*Remove all boxes from the list and the current box*/ DeleteListOfBoxes(&solutions); } DeleteBox(&b); nt++; if ((ntries!=NO_UINT)&&(nt==ntries)) end=TRUE; } if (f_out_box!=NULL) { DeleteFileName(&fsols_box); fclose(f_out_box); } if (f_out_point!=NULL) { fclose(f_out_point); DeleteFileName(&fsols_point); } /*Restore the user given small_sigma and number of solutions*/ ChangeParameter(CT_SMALL_SIGMA,ms,p); ChangeParameter(CT_N_SOLUTIONS,nsols,p); free(attempts); free(bl); free(fv); free(ind2fv); free(sol); UnUpdateCuikSystem(cs); VariablesFromBox(&orig_ranges,&(cs->orig_variables)); DeleteBox(&orig_ranges); return(!end); } unsigned int CuikNewtonSimp(Tparameters *p,double *x,TCuikSystem *cs) { boolean converged=FALSE; unsigned int out=DIVERGED; if (UpdateCuikSystem(p,cs)) { if (cs->simp_nequations==0) { out=CONVERGED_IN_BOX; } else { TNewton newton; double *Jx_d; double *b_d; double epsilon,nullSingularValue; double errorVal; int err; unsigned int nStep,nStepMax; #if (_DEBUG>2) { unsigned int i; printf("Starting Newton Iteration form: ["); for(i=0;i<cs->simp_nvariables;i++) printf("%f ",x[i]); printf("]\n"); } #endif InitNewton(cs->simp_nee,cs->simp_nvariables,&newton); Jx_d=GetNewtonMatrixBuffer(&newton); b_d=GetNewtonRHBuffer(&newton); epsilon=GetParameter(CT_EPSILON,p); nullSingularValue=epsilon/100; nStepMax=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p); if (nStepMax==0) Error("Parameter MAX_NEWTON_ITERATIONS must be larger than 0 to use CuikNewton"); nStep=0; while((!converged)&&(nStep<nStepMax)) { EvaluateJacobianInVector(x,cs->simp_nee,cs->simp_nvariables,Jx_d,&(cs->J)); EvaluateEqualityEquations(FALSE,x,b_d,&(cs->simp_equations)); err=NewtonStep(nullSingularValue,x,&errorVal,&newton); if (err) nStep=nStepMax; else { #if (_DEBUG>2) { unsigned int i; printf(" Iteration: %u error: %g",nStep,errorVal); #if (_DEBUG>3) printf(" x: [\n"); for(i=0;i<cs->simp_nvariables;i++) printf("%f ",x[i]); printf("]"); #endif printf("\n"); } #endif /* stopCriterion test */ if(errorVal<epsilon) converged=TRUE; nStep++; } } if (cs->simp_tp!=NULL) ArrayPi2Pi(cs->simp_nvariables,cs->simp_tp,x); DeleteNewton(&newton); if ((converged)&&(ErrorInSimpCSEquations(p,x,cs)<epsilon)) out=CONVERGED_IN_GLOBAL; else out=DIVERGED; } } else Error("Inconsistent input cuiksystem"); return(out); } unsigned int CuikNewtonInBox(Tparameters *p,Tbox *bIn,double *sol,Tbox *b_sol,TCuikSystem *cs) { boolean converged=FALSE; unsigned int out=DIVERGED; if (UpdateCuikSystem(p,cs)) { if (cs->simp_nequations==0) { unsigned int i; /* The system of equations is empty -> just pic a random value for the variables */ for(i=0;i<cs->orig_nvariables;i++) sol[i]=randomInInterval(GetBoxInterval(i,bIn)); InitBoxFromPoint(cs->orig_nvariables,sol,b_sol); out=CONVERGED_IN_BOX; } else { Tbox bsimp; Tinterval c,*r; unsigned int nv,ne,bs; unsigned int i,j,k,l; double *m,*h; double *x; double *Jx_d; double *b_d; /* Newton required variables */ TNewton newton; double epsilon; double nullSingularValue; double errorVal; unsigned int nStep,nStepMax; int err; Tbox box; bs=GetBoxNIntervals(bIn); if (cs->orig_nvariables<bs) Error("Box size missmatch in CuikNewtonInBox"); else { if (cs->orig_nvariables>bs) { if (cs->orig_nvariables==(bs+GetNumDummyVariables(&(cs->orig_variables)))) { /* We are given a solution box without the dummy vars */ /* We need to compute the values for the dummy vars from the system ones*/ GenerateInitialBox(&box,cs); /*all variables to initial ranges*/ SetBoxSubset(cs->orig_systemVar,bIn,&box); /* only dummies to initial ranges */ RegenerateSolution(p,&box,cs); /* define dummies from system variables */ } else Error("Box size missmatch in CuikNewtonInBox"); } else CopyBox(&box,bIn); } nStepMax=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p); if (nStepMax==0) Error("Parameter MAX_NEWTON_ITERATIONS must be larger than 0 to use CuikNewton"); SimpleFromOriginal(&box,&bsimp,cs->orig2s); /* We will add some variables and equations to deal with ranges */ #if (NEWTON_WITHIN_RANGES) nv=cs->simp_nvariables+cs->simp_nvariables; ne=cs->simp_nee+cs->simp_nvariables; #else nv=cs->simp_nvariables; ne=cs->simp_nee; #endif /* Space for the variable ranges */ NEW(m,cs->simp_nvariables,double); NEW(h,cs->simp_nvariables,double); for(i=0;i<cs->simp_nvariables;i++) { r=GetBoxInterval(i,&bsimp); m[i]=IntervalCenter(r); h[i]=IntervalSize(r)/2.0; } /* Matrices and arrays used in the Newton iteration */ NEW(x,nv,double); for(i=0;i<cs->simp_nvariables;i++) x[i]=randomInInterval(GetBoxInterval(i,&bsimp)); for(i=cs->simp_nvariables,j=0;i<nv;i++,j++) x[i]=asin((x[j]-m[j])/h[j]); #if (_DEBUG>2) { printf("Starting Newton Iteration form: x=["); for(i=0;i<nv;i++) printf("%f ",x[i]); printf("]\n"); } #endif InitNewton(ne,nv,&newton); Jx_d=GetNewtonMatrixBuffer(&newton); k=ne*nv; if (k!=(cs->simp_nee*cs->simp_nvariables)) { /* If we have limit constraints just init the full buffer to zero. */ for(i=0;i<k;i++) Jx_d[i]=0; } b_d=GetNewtonRHBuffer(&newton); epsilon=GetParameter(CT_EPSILON,p); nullSingularValue=epsilon/100; nStep=0; while((!converged)&&(nStep<nStepMax)) { EvaluateJacobianInVector(x,ne,nv,Jx_d,&(cs->J)); EvaluateEqualityEquations(FALSE,x,b_d,&(cs->simp_equations)); for(i=cs->simp_nvariables,j=0,l=cs->simp_nee;i<nv;i++,j++,l++) { /* 'j' is the index for the original variable 'v' */ /* 'i' is the index for the new variable 'q' */ NewtonSetMatrix(l,j,1,&newton); NewtonSetMatrix(l,i,-h[j]*cos(x[i]),&newton); NewtonSetRH(l,(x[j]-m[j]-h[j]*sin(x[i])),&newton); } errorVal=Norm(ne,b_d); //fprintf(stderr,"%u Newton Error: %g\n",nStep,errorVal); converged=(errorVal<epsilon); if (!converged) { err=NewtonStep(nullSingularValue,x,&errorVal,&newton); if (err) nStep=nStepMax; else { #if (_DEBUG>2) printf(" Iteration: %u error: %g",nStep,errorVal); #if (_DEBUG>3) printf(" x: [\n"); for(i=0;i<cs->simp_nvariables;i++) printf("%f ",x[i]); printf("]"); #endif printf("\n"); #endif nStep++; } } } DeleteNewton(&newton); if (cs->simp_tp!=NULL) ArrayPi2Pi(cs->simp_nvariables,cs->simp_tp,x); for(i=0;i<cs->simp_nvariables;i++) { NewInterval(x[i],x[i],&c); SetBoxInterval(i,&c,&bsimp); } CopyBox(b_sol,&box); UpdateOriginalFromSimple(&bsimp,b_sol,cs->orig2s); /* Some dummy variables in original system might not be present in the simplified system but their value can be trivially deduced from the system variables*/ RegenerateSolution(p,b_sol,cs); /*At this point b_sol must be a punctual box (fully defined) */ for(i=0;i<cs->orig_nvariables;i++) sol[i]=IntervalCenter(GetBoxInterval(i,b_sol)); if (!converged) //((!converged)||(ErrorInSolution(b_sol,cs)>epsilon)) out=DIVERGED; else { Tbox init_box; GenerateInitialBox(&init_box,cs); if ((ErrorInInequalities(b_sol,cs)>epsilon)|| (!PointInBox(cs->orig_notDummyVar,cs->orig_nvariables,sol,epsilon,&init_box))) out=CONVERGED_OUTSIDE_GLOBAL; else { if (PointInBox(cs->orig_systemVar,cs->orig_nvariables,sol,epsilon,&box)) out=CONVERGED_IN_BOX; else out=CONVERGED_IN_GLOBAL; } DeleteBox(&init_box); } DeleteBox(&bsimp); free(x); free(m); free(h); DeleteBox(&box); } } else Error("Inconsistent input cuiksystem"); return(out); } /* Find a solution of a cuiksystem set of equations using the Newton-Rhapson method. If the system is undetermined, the method is based on the Moor-Penrose generalised inverse. The method can diverge if the initial point is far from the solutions of the system. */ boolean CuikNewton(Tparameters *p,double *sol,Tbox *b_sol,TCuikSystem *cs) { Tbox init_box; boolean converged; GenerateInitialBox(&init_box,cs); converged=((CuikNewtonInBox(p,&init_box,sol,b_sol,cs)&(CONVERGED_IN_BOX|CONVERGED_IN_GLOBAL))>0); DeleteBox(&init_box); return(converged); } unsigned int CuikGradientInBox(Tparameters *p, Tbox *bIn,double *sol,Tbox *b_sol,TCuikSystem *cs) { boolean converged=FALSE; unsigned int out=DIVERGED; if (UpdateCuikSystem(p,cs)) { if (cs->simp_nequations==0) { unsigned int i; /* The system of equations is empty -> just pic a random value for the variables */ for(i=0;i<cs->orig_nvariables;i++) sol[i]=randomInInterval(GetBoxInterval(i,bIn)); InitBoxFromPoint(cs->orig_nvariables,sol,b_sol); out=CONVERGED_IN_BOX; } else { Tbox box,bsimp; double *x,*nx,*f,*J,*g; double alpha,c,t,tau; unsigned int bs,i,k,nSteps,ne; double error,e,epsilon,d; boolean done,stalled; Tinterval range,*is; unsigned int bounds; bounds=1; /* 0: do not consider 1: weigth 2:crop */ bs=GetBoxNIntervals(bIn); if (cs->orig_nvariables<bs) Error("Box size missmatch in CuikGradientInBox"); else { if (cs->orig_nvariables>bs) { if (cs->orig_nvariables==(bs+GetNumDummyVariables(&(cs->orig_variables)))) { /* We are given a solution box without the dummy vars */ /* We need to compute the values for the dummy vars from the system ones*/ GenerateInitialBox(&box,cs); /*all variables to initial ranges*/ SetBoxSubset(cs->orig_systemVar,bIn,&box); /* only dummies to initial ranges */ RegenerateSolution(p,&box,cs); /* define dummies from system variables */ } else Error("Box size missmatch in CuikGradientInBox"); } else CopyBox(&box,bIn); } SimpleFromOriginal(&box,&bsimp,cs->orig2s); is=GetBoxIntervals(&bsimp); epsilon=GetParameter(CT_EPSILON,p); /* initial point */ NEW(x,cs->simp_nvariables,double); for(i=0;i<cs->simp_nvariables;i++) x[i]=randomInInterval(&(is[i])); /* Space to evaluate the equations */ if (bounds==1) ne=cs->simp_nee+cs->simp_nvariables; else ne=cs->simp_nee; NEW(nx,cs->simp_nvariables,double); /* new x */ NEW(f,ne,double); /* evaluation of equations */ NEW(g,cs->simp_nvariables,double); /* gradient at x */ NEWZ(J,ne*cs->simp_nvariables,double); /* Jacobian of the equations (initialized to 0) */ nSteps=1; converged=FALSE; stalled=FALSE; while((!converged)&&(!stalled)) { EvaluateJacobianInVector(x,ne,cs->simp_nvariables,J,&(cs->J)); EvaluateEqualitySparseEquations(x,f,&(cs->simp_equations)); /* only enter the loop if bounds==1 */ for(k=cs->simp_nee,i=0;k<ne;k++,i++) { d=DistanceToInterval(x[i],&(is[i])); f[k]=d*d; J[RC2INDEX(k,i,ne,cs->simp_nvariables)]=2*d; } error=Norm(ne,f); if (nSteps%1000==1) fprintf(stderr," Error %u: %g\n",nSteps,error); converged=(error<epsilon/10); if (!converged) { /* obtain the gradient of f1^2+...+f_nv^2 */ TMatrixVectorProduct(ne,cs->simp_nvariables,J,f,g); e=Norm(cs->simp_nvariables,g); if (e<epsilon/100) { fprintf(stderr," Gradient norm: %g\n",e); stalled=TRUE; } else { /* Adjust alpha Apply backtracking line search with c=tau=0.5 and with p=-gradient http://en.wikipedia.org/wiki/Backtracking_line_search */ done=FALSE; alpha=0.1; /* initial guess */ c=tau=0.5; /* set c,tau parameters */ t=-c*Norm(cs->simp_nvariables,g); /* t=-c*m, m=p^t*g=-g^t*g (with p=-g) */ while((!done)&&(!stalled)) { /* nx = x + alpha*p = x -alpha*g (cropped to the box if required) */ SumVectorScale(cs->simp_nvariables,x,-alpha,g,nx); if (bounds==2) Crop2Box(NULL,cs->simp_nvariables,nx,&bsimp); /* evaluate f(nx) */ EvaluateEqualitySparseEquations(nx,f,&(cs->simp_equations)); /* only enter the loop if bounds==1 */ for(k=cs->simp_nee,i=0;k<ne;k++,i++) { d=DistanceToInterval(nx[i],&(is[i])); f[k]=d*d; } e=Norm(ne,f); /* Test if the decrease in error is enough using Armijo-Goldstein condition */ if ((error-e)<alpha*t) { alpha*=tau; stalled=(alpha<epsilon); } else done=TRUE; } if (!stalled) memcpy(x,nx,cs->simp_nvariables*sizeof(double)); /* x<-nx */ } } nSteps++; } if (cs->simp_tp!=NULL) ArrayPi2Pi(cs->simp_nvariables,cs->simp_tp,x); for(i=0;i<cs->simp_nvariables;i++) { NewInterval(x[i],x[i],&range); SetBoxInterval(i,&range,&bsimp); } CopyBox(b_sol,&box); UpdateOriginalFromSimple(&bsimp,b_sol,cs->orig2s); /* Some dummy variables in original system might not be present in the simplified system but their value can be trivially deduced from the system variables*/ RegenerateSolution(p,b_sol,cs); /*At this point b_sol must be a punctual box (fully defined) */ for(i=0;i<cs->orig_nvariables;i++) sol[i]=IntervalCenter(GetBoxInterval(i,b_sol)); if (!converged) //((!converged)||(ErrorInSolution(b_sol,cs)>epsilon)) out=DIVERGED; else { Tbox init_box; GenerateInitialBox(&init_box,cs); if ((ErrorInInequalities(b_sol,cs)>epsilon)|| (!PointInBox(cs->orig_notDummyVar,cs->orig_nvariables,sol,epsilon,&init_box))) out=CONVERGED_OUTSIDE_GLOBAL; else { if (PointInBox(cs->orig_systemVar,cs->orig_nvariables,sol,epsilon,&box)) out=CONVERGED_IN_BOX; else out=CONVERGED_IN_GLOBAL; } DeleteBox(&init_box); } free(x); free(f); free(g); free(J); DeleteBox(&box); DeleteBox(&bsimp); } } else Error("Inconsistent input cuiksystem"); return(out); } /* Find a solution of a cuiksystem set of equations using a gradient descent method. */ boolean CuikGradient(Tparameters *p,double *sol,Tbox *b_sol,TCuikSystem *cs) { Tbox init_box; boolean converged; GenerateInitialBox(&init_box,cs); converged=((CuikGradientInBox(p,&init_box,sol,b_sol,cs)&(CONVERGED_IN_BOX|CONVERGED_IN_GLOBAL))>0); DeleteBox(&init_box); return(converged); } /* Takes a cuik systema and returns all solutions. Solutions are stored in file 'f_out' (if defined) and in list 'sol' (if defined), or both. This procedure is used for single-cpu versions of Cuik. */ void SolveCuikSystem(Tparameters *p, boolean restart,char *fstate,Tbox *searchSpace, FILE *f_out,Tlist *sol,TCuikSystem *cs) { Theap boxes; #if (_DEBUG>1) unsigned int nbox=0; #endif Tbox b; unsigned int c; /* output of ReduceBox */ unsigned int current_level; /* level of the current box in the search three */ Tbox init_box; boolean done; unsigned int nb; /*boxes for recovery mode*/ unsigned int statePeriod; unsigned int nsols; if (!cs->scalar) Error("SolveCuikSystem only operates on scalar systems"); /************************************************************************************/ /************************************************************************************/ /************************************************************************************/ if (UpdateCuikSystem(p,cs)) { if (cs->simp_empty) { Tbox b; /* The system of equations is empty -> just pic a random value for the variables */ InitBox(cs->simp_nvariables,NULL,&b); PostProcessBox(p,REDUCED_BOX_WITH_SOLUTION,f_out,sol,&boxes,&b,cs); DeleteBox(&b); } else { switch(cs->searchMode) { case DEPTH_FIRST_SEARCH: InitHeapOfBoxes(CmpBoxDepthFirst,NULL,&boxes); break; case BREADTH_FIRST_SEARCH: InitHeapOfBoxes(CmpBoxBreadthFirst,NULL,&boxes); break; case MINIMIZATION_SEARCH: InitHeapOfBoxes(CmpBoxesEquation,(void *)cs,&boxes); break; } if ((restart)&&(fstate!=NULL)) { Tlist pboxes; LoadCSState(fstate,&pboxes,cs); AddList2Heap(&pboxes,&boxes); DeleteListOfBoxes(&pboxes); } else { if (searchSpace==NULL) { BoxFromVariables(&init_box,&(cs->variables)); AddBox2HeapOfBoxes(&init_box,&boxes); DeleteBox(&init_box); } else { SimpleFromOriginal(searchSpace,&init_box,cs->orig2sd); AddBox2HeapOfBoxes(&init_box,&boxes); } InitStatistics(1,HeapOfBoxesVolume(cs->systemVar,&boxes),&(cs->st)); } current_level=0; nb=0; statePeriod=(unsigned int)GetParameter(CT_STATE_PERIOD,p); nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p); done=FALSE; /*the cuik solve process itself*/ do { if(!HeapEmpty(&boxes)) { /*Get a new box*/ if ((statePeriod>0)&&(fstate!=NULL)) { nb++; if (nb==statePeriod) { Tlist pboxes; Heap2List(&pboxes,&boxes); SaveCSState(fstate,&pboxes,cs); DeleteListOfBoxes(&pboxes); nb=0; } } NewBoxProcessed(&(cs->st)); /*The box is extracted to avoid another process to get the same box*/ ExtractMinElement(&b,&boxes); current_level=GetBoxLevel(&b); NewMaxLevel(current_level,&(cs->st)); #if (_DEBUG>0) fprintf(stderr,"<%g %g>[%u]", GetBoxVolume(cs->systemVar,&b), GetBoxSize(cs->systemVar,&b), current_level); #endif #if (_DEBUG>1) printf("\n\n%u: Analizing box: ",nbox); nbox++; PrintBox(stdout,&b); printf(" Box level : %u\n",GetBoxLevel(&b)); printf(" Box volume : %g\n",GetBoxVolume(cs->systemVar,&b)); printf(" Box size : %g\n",GetBoxSize(cs->systemVar,&b)); if (cs->searchMode==MINIMIZATION_SEARCH) printf(" Box penalty : %g\n",EvaluateEqMin((void *)&b,(void *)cs)); #endif /* Reduce the box by all but dummy vars */; c=ReduceBox(p,~DUMMY_VAR,&b,cs); #if (_DEBUG>0) fprintf(stderr," -> "); #endif PostProcessBox(p,c,f_out,sol,&boxes,&b,cs); if (nsols>0) done=(GetNSolutionBoxes(&(cs->st))>=nsols); DeleteBox(&b); } } while((!done)&&(!HeapEmpty(&boxes))); /*Until everything is completed*/ DeleteHeap(&boxes); /*for sanity we delete the empty list*/ PrintStatistics((f_out==NULL?stdout:f_out),&(cs->st)); } } } #if (_USE_MPI) /* In multi-cpu versions we use a MPI version of CuikSolve One of the CPUs takes the role of scheduler in charge of managing the lists of boxes pending to be processed and classifing boxes out of reduction process as solutions of boxes to be split. The rest of CPUs take the charge of reducing boxes (i.e., of executing ReduceBox to the boxes received from the scheduler) and of returning the resulting boxes (with the associated result code) to the scheduler. The scheduler has to take into account that some child nodes can 'die' while reducing boxes. So it has to keep track of when a box was sent to a child and prediodically check whether a timeout was been reached. If so, the corresponding processor is considered as 'dead' the box sent is recovered and added to the list of boxes to be processed (i.e., send to other child nodes still alive). The scheduler should considere the extreme case where all child process die and should take care of "awakening" dead processors. This is not implemented.... till now. */ void MPI_SolveCuikSystem(Tparameters *p, boolean restart,char *fstate,Tbox *searchSpace, FILE *f_out,TCuikSystem *cs) { Theap boxes; /*queued boxes*/ Tbox b; unsigned int c; unsigned int nr; unsigned int current_level; /*Variables to set up the parallelism*/ unsigned int in_process; /* number of boxes send to child processors and still in process */ unsigned int available; /* number of child processors available */ signed int np; /* number of processors used (np-1) is the number of childs (process 0 is the scheduler) */ MPI_Status status; /* Output status of a MPI command */ MPI_Request *request; /* Communication request. When the scheduller sends out a box is starts a communication request */ unsigned int buffer_size; /* Size of a buffer of doubles where we store the information of a box */ double **buffers_out; /* boxes send to the child processors */ double **buffers_in; /* boxes returned by the child processors */ signed int i,completed; /* MPI_Testany returns completed=1 if any of the pending communications requests has been replied (then, 'i' is the number of the compleated request)*/ boolean *lost_packet; /* true if a box was never returned */ time_t *time_stamp; /* time when we send out a box */ time_t deadline; /* deadline (in seconds) used to compute the maximum expected return time for a box*/ Tbox init_box; /* initial search space */ unsigned int nb; unsigned int statePeriod; unsigned int nsols; boolean done; if (!cs->scalar) Error("MPI_SolveCuikSystem only operates on scalar systems"); /*lowest possible priority but not as low as that of the children processors*/ /*setpriority(PRIO_PROCESS,0,PRIO_MAX-1); */ MPI_Comm_size(MPI_COMM_WORLD,&np); /*total number of processes (take into account that this routine is process number 0)*/ if (UpdateCuikSystem(p,cs)) { switch(cs->searchMode) { case DEPTH_FIRST_SEARCH: InitHeapOfBoxes(CmpBoxDepthFirst,NULL,&boxes); break; case BREADTH_FIRST_SEARCH: InitHeapOfBoxes(CmpBoxBreadthFirst,NULL,&boxes); break; case MINIMIZATION_SEARCH: InitHeapOfBoxes(CmpBoxesEquation,(void *)cs,&boxes); break; } BoxFromVariables(&init_box,&(cs->variables)); /* Reserve space for the boxes sent/received and associated information */ /*All boxes are the same size as the initial one*/ buffer_size=GetBoxBufferSize(&init_box); if ((restart)&&(fstate!=NULL)) { Tlist pboxes; LoadCSState(fstate,&pboxes,cs); AddList2Heap(&pboxes,&boxes); DeleteListOfBoxes(&pboxes); } else { if (searchSpace==NULL) AddBox2HeapOfBoxes(&init_box,&boxes); else { Tbox lb; SimpleFromOriginal(searchSpace,&lb,cs->orig2sd); AddBox2HeapOfBoxes(&lb,&boxes); DeleteBox(&lb); } InitStatistics(np,HeapOfBoxesVolume(cs->systemVar,&boxes),&(cs->st)); } DeleteBox(&init_box); current_level=0; NEW(buffers_out,np,double*); NEW(buffers_in,np,double*); NEW(request,np,MPI_Request); NEW(lost_packet,np,boolean); NEW(time_stamp,np,time_t); for(i=1;i<np;i++) { request[i]=MPI_REQUEST_NULL; NEW(buffers_out[i],buffer_size,double); NEW(buffers_in[i],buffer_size,double); lost_packet[i]=FALSE; } request[0]=MPI_REQUEST_NULL; /* Processor 0 is the scheduler, do not use it as a child */ in_process=0; available=(np-1); nb=0; statePeriod=GetParameter(CT_STATE_PERIOD,p); nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p); done=FALSE; /*the cuik solve process itself*/ do { if ((!done)&& /*we don't have enough solutions*/ (!HeapEmpty(&boxes))&& /* there is something to be processes */ (available>0)) /* and someone ready to process it */ { /* Search for a free child (at least one must exists) */ i=1; while ((i<np)&&(request[i]!=MPI_REQUEST_NULL)) i++; if (i==np) Error("wrong number of available processors"); else { if ((statePeriod>0)&&(fstate!=NULL)) { nb++; if (nb==statePeriod) { Tbox btmp; unsigned int ctmp,ntmp; Tlist pboxes; unsigned int kk; Heap2List(&pboxes,&boxes); for(kk=1;kk<np;kk++) { if (request[kk]!=MPI_REQUEST_NULL) { InitBox(cs->nvariables,NULL,&btmp); Buffer2Box(&ctmp,&ntmp,buffers_out[kk],&btmp); AddFirstElement((void *)&btmp,&pboxes); } } SaveCSState(fstate,&pboxes,cs); DeleteListOfBoxes(&pboxes); nb=0; } } /*Get a new box*/ ExtractMinElement(&b,&boxes); /* Transform the box into a buffer of doubles */ Box2Buffer(REDUCED_BOX,0,buffers_out[i],&b); /* Send it to the iddle child processors */ /* and start waiting for the reply (i.e., the reduced box) */ if (MPI_Send(buffers_out[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD)==MPI_SUCCESS) { /* The box is sent and now we start waiting for it */ if (MPI_Irecv(buffers_in[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD,&(request[i]))==MPI_SUCCESS) { current_level=GetBoxLevel(&b); NewBoxProcessed(&(cs->st)); NewMaxLevel(current_level,&(cs->st)); /* One more box is in process */ in_process++; /* One less processor is available */ available--; #if (_DEBUG>0) /* Inform about the box launchig */ fprintf(stderr,"b<v:%g, s:%g, l:%u>-> %u\n", GetBoxVolume(cs->systemVar,&b), GetBoxSize(cs->systemVar,&b), current_level,i); /* fprintf(stderr," A:%d P:%d Q:%u\n", available,in_process,HeapSize(&boxes)); */ #endif /* Store the time at which we sent out the box */ time_stamp[i]=time(NULL); /* and, mark the sent box as not lost */ lost_packet[i]=FALSE; #if (_DEBUG>1) printf("Sending box to processors : %u (iddle -> %u box_in_list-> %u)\n", i,np-in_process-1,HeapSize(&boxes)); printf(" Box: "); PrintBox(stdout,&b); #endif DeleteBox(&b); } else { /*The box will never be back: add it to the list and free the processor */ #if (_DEBUG>0) fprintf(stderr,"RF-> %u\n",i); #endif AddBox2HeapOfBoxes(&b,&boxes); request[i]=MPI_REQUEST_NULL; } } else { /* We didn't manage to send out the box, just return it to the boxes to be processes*/ #if (_DEBUG>0) fprintf(stderr,"SF-> %u\n",i); #endif AddBox2HeapOfBoxes(&b,&boxes); } } } /* see if we already got any reply from the slaves :-) */ if ((MPI_Testany(np,request,&i,&completed,&status)==MPI_SUCCESS)&& (completed)) { /* if 'completed' 'i' is the request completed */ #if (_DEBUG>1) printf("Receiving box from processors : %u\n",i); #endif available++; /* either if lost or not, the processor becomes available from now on */ request[i]=MPI_REQUEST_NULL; if (!lost_packet[i]) { /* If so, reconstruct the output box and analyze it */ InitBox(cs->nvariables,NULL,&b); Buffer2Box(&c,&nr,buffers_in[i],&b); AddNBoxReductions(nr,&(cs->st)); in_process--; /* lost ones are already discounted when classified as lost (to be able to finish even if lost ones exits)*/ #if (_DEBUG>0) fprintf(stderr," %u->b<v:%g s:%g l:%u>(t=%lu): ", i, GetBoxVolume(cs->systemVar,&b), GetBoxSize(cs->systemVar,&b), GetBoxLevel(&b), time(NULL)-time_stamp[i]); /* fprintf(stderr," A:%d P:%d Q:%u\n", available,in_process,HeapSize(&boxes)); */ #endif PostProcessBox(p,c,f_out,NULL,&boxes,&b,cs); if (nsols>0) done=(GetNSolutionBoxes(&(cs->st))>=nsols); DeleteBox(&b); } #if (_DEBUG>0) else { /* We receive a box that was thought to be lost. The only think we do is to mark the child as available again by setting request[i]=MPI_REQUEST_NULL; below */ fprintf(stderr," lb[%u](t=%lu > %u)\n",i, time(NULL)-time_stamp[i],MPI_TREAT_BOX_TIMEOUT(cs)); } #endif } /* See if one of the send boxes is lost. All boxes sent before the deadline are considered lost. Lost boxes are recovered and added to the list of pending boxes. The processor to which the box was assigned is discarted for future jobs. */ deadline=time(NULL)-(time_t)MPI_TREAT_BOX_TIMEOUT(cs); for(i=1;i<np;i++) { if ((!lost_packet[i])&& /*not already lost*/ (request[i]!=MPI_REQUEST_NULL)&& /*and we are waiting for a reply*/ (time_stamp[i]<deadline)) /*for too long actually*/ { /* we considere the sub-task as lost, we add the box for further process by another computer and we mark the current message as lost */ lost_packet[i]=TRUE; /* mark the packet as lost */ InitBox(cs->nvariables,NULL,&b); /*Recover it and put it again in the list of boxes to be processed*/ Buffer2Box(&c,&nr,buffers_out[i],&b); /* Error code (c) and additional information (nr) are empty (this is a box whose process was not concluded)*/ NewLostBox(&(cs->st)); #if (_DEBUG>0) fprintf(stderr," l[%u] (elapsed %lu)\n",i,time(NULL)-time_stamp[i]); #endif /* a time out tipically means a error in the simplex */ PostProcessBox(p,ERROR_IN_PROCESS,f_out,NULL,&boxes,&b,cs); DeleteBox(&b); in_process--; /* one less box is in process (Observe that the processors is not marked as available) */ } } fflush(stderr); /* Repeat until we don't have enough solutions and there are still some boxes from where we can get solutions. If we already have all the desired solutions but some boxes are in_process, we wait untill their process finishes (so that all processors are ready to receive the kill signal) */ } while(((!done)&&(!HeapEmpty(&boxes)))||(in_process>0)); /* Send a magic packed to the child so that they kill themselves */ for(i=1;i<np;i++) { if (request[i]!=MPI_REQUEST_NULL) { /*we have a pending communication with this processor -> cancel it*/ MPI_Cancel(&(request[i])); } else { /*nothing pending with this processors, just order it to die*/ buffers_out[i][0]=-1.0; MPI_Send(buffers_out[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD); } } free(request); free(lost_packet); free(time_stamp); DeleteHeap(&boxes); if (f_out!=NULL) { fprintf(f_out,"\n\nCuik executed in %u (%u) child processors\n",available,np-1); PrintStatistics(f_out,&(cs->st)); } DeleteStatistics(&(cs->st)); for(i=1;i<np;i++) { free(buffers_in[i]); free(buffers_out[i]); } free(buffers_in); free(buffers_out); } } /* This is the process executed by each child process */ void MPI_TreatBox(Tparameters *p,TCuikSystem *cs) { if (!cs->scalar) Error("MPI_TreatBox only operates on scalar systems"); if (UpdateCuikSystem(p,cs)) { boolean end; unsigned int n; double *buffer; unsigned int c,nr; Tbox b; MPI_Status status; InitBox(cs->nvariables,NULL,&b); n=GetBoxBufferSize(&b); NEW(buffer,n,double); /* A child can be in execution in computers not only devoted to cuik. We reduce the priority of the cuik process to allow other processes (those own by the owners of the machines) to run smoothly. This way we can enlarge the cluster of procesors to almost all computers in our Lab. In the future we have to develop programs to check which computers are on and to add them into the machine list (i.e., the members of the cluster) */ /*setpriority(PRIO_PROCESS,0,PRIO_MAX); */ end=FALSE; /* While the kill buffer is not received */ while(!end) { /* Get new box from the master */ if (MPI_Recv(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD,&status)==MPI_SUCCESS) { /* The first double is used to send control messages between the scheduler and the slave. If negative, the slave dies*/ if (buffer[0]<0) end=TRUE; else { /* If not the kill buffer, recover the box out of the buffer */ Buffer2Box(&c,&nr,buffer,&b); ResetNBoxReductions(&(cs->st)); /* Let's count the box reductions for this box shrink only*/ #if (_DEBUG>1) printf("Box from main processor:"); PrintBox(stdout,&b); fflush(stdout); #endif /* And reduce it */ c=ReduceBox(p,~DUMMY_VAR,&b,cs); #if (_DEBUG>1) printf("Box out of ReduceBox (%u):",c); PrintBox(stdout,&b); fflush(stdout); #endif /* Then pack the result into another buffer */ Box2Buffer(c,GetNBoxReductions(&(cs->st)),buffer,&b); /* and send it back to the master */ #if (_DEBUG>1) if (MPI_Send(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD)!=MPI_SUCCESS) printf("Sending to master failed\n"); #else MPI_Send(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD); #endif } } #if (_DEBUG>1) else printf("Receive from master failed\n"); #endif } DeleteBox(&b); free(buffer); } } #endif /* Returns a box defined by the ranges for the variables given by the user in the input file. This is the initial search space. */ void GenerateInitialBox(Tbox *box,TCuikSystem *cs) { BoxFromVariables(box,&(cs->orig_variables)); } void GenerateSimpInitialBox(Tparameters *p,Tbox *box,TCuikSystem *cs) { if (!UpdateCuikSystem(p,cs)) Error("Inconsistent system in GenerateSimpInitialBox"); BoxFromVariables(box,&(cs->simp_variables)); } boolean RegenerateSolution(Tparameters *p,Tbox *b,TCuikSystem *cs) { boolean ok; if (UpdateCuikSystem(p,cs)) { unsigned int i; Tbox bInit; double epsilon,rho; Tinterval all; /* If we set the dummies to range [-INF,INF] they are not adjusted via crop. */ NewInterval(-INF/2,INF/2,&all); epsilon=GetParameter(CT_EPSILON,p); rho=GetParameter(CT_RHO,p); InitBox(cs->orig_nvariables,NULL,&bInit); /* System and secondary vars already have value in the input box but dummies and cartesian variables probably not. These are set to inf range to avoid any limit in their value when regenerated (boxes commming from Newton can have extrange values in dummy variables. */ for(i=0;i<cs->orig_nvariables;i++) { if ((IsDummyVariable(i,&(cs->orig_variables)))|| (IsCartesianVariable(i,&(cs->orig_variables)))) SetBoxInterval(i,&all,b); } DeleteBox(&bInit); ok=TRUE; /* First we define the value of the dummy variables from the system ones. They are related by dymmy equations and, given the system varibles, the dummy variables can be easily defined via crop. */ for(i=0;((ok)&&(i<cs->orig_nequations));i++) { if (IsDummyEquation(i,&(cs->orig_equations))) ok=(CropEquation(i,DUMMY_VAR,epsilon,rho,b,&(cs->orig_variables),&(cs->orig_equations))!=EMPTY_BOX); } /* Now we try to define the cartesian variables from the system and dummy ones. The separating plane cartesian variables can not be properly bounded this way but the ones for body vertexes can (and they are the relevant ones) */ for(i=0;((ok)&&(i<cs->orig_nequations));i++) { if (IsCoordEquation(i,&(cs->orig_equations))) ok=(CropEquation(i,CARTESIAN_VAR,epsilon,rho,b,&(cs->orig_variables),&(cs->orig_equations))!=EMPTY_BOX); } } else ok=FALSE; return(ok); } unsigned int RegenerateSolutionPoint(Tparameters *p,double *pt,double **rp,TCuikSystem *cs) { unsigned int i,k; Tbox b; if (!UpdateCuikSystem(p,cs)) Error("Inconsistent system in RegenerateSolutionPoint"); NEW(*rp,cs->orig_nvariables,double); k=0; for(i=0;i<cs->orig_nvariables;i++) { /*The input box only has values for the input variables*/ if (cs->orig_systemVar[i]) { (*rp)[i]=pt[k]; k++; } else (*rp)[i]=0.0; /*Non system variables are set to 0. This value is not used */ } InitBoxFromPoint(cs->orig_nvariables,*rp,&b); if (!RegenerateSolution(p,&b,cs)) Error("Invalid solution point in RegenerateSolutionPoint"); k=0; for(i=0;i<cs->orig_nvariables;i++) { /*The input box only has values for the input variables (system and secondary)*/ if (!cs->orig_systemVar[i]) (*rp)[i]=IntervalCenter(GetBoxInterval(i,&b)); } DeleteBox(&b); return(cs->orig_nvariables); } void RegenerateOriginalBox(Tparameters *p,Tbox *boxS,Tbox *boxO,TCuikSystem *cs) { if (UpdateCuikSystem(p,cs)) { BoxFromVariables(boxO,&(cs->orig_variables)); UpdateOriginalFromSimple(boxS,boxO,cs->orig2s); } else Error("Inconsistent input cuiksystem"); } unsigned int RegenerateOriginalPoint(Tparameters *p,double *s,double **o, TCuikSystem *cs) { if (UpdateCuikSystem(p,cs)) { PointFromVariables(o,&(cs->orig_variables)); UpdateOriginalPointFromSimple(s,*o,cs->orig2s); } else Error("Inconsistent input cuiksystem"); return(cs->orig_nvariables); } unsigned int GenerateSimplifiedPoint(Tparameters *p,double *o,double **s,TCuikSystem *cs) { if (UpdateCuikSystem(p,cs)) SimplePointFromOriginal(o,s,cs->orig2s); else Error("Inconsistent input cuiksystem"); return(cs->simp_nvariables); } unsigned int SimplifyBooleanArray(Tparameters *p,boolean *bo,boolean **bs, TCuikSystem *cs) { if (UpdateCuikSystem(p,cs)) { unsigned int i,k; NEW(*bs,cs->simp_nvariables,boolean); k=0; for(i=0;i<cs->orig_nvariables;i++) { if (IsInSimple(i,cs->orig2s)) { (*bs)[k]=bo[i]; k++; } } if (k!=cs->simp_nvariables) Error("Wrong number of variables in SimplifyBooleanArray"); } else Error("Inconsistent input cuiksystem"); return(cs->simp_nvariables); } /* Selects one dimension along which to split box 'b'. The dimension can be selected according to the size or according to the error that each variable induce in each equation. This is similar to ComputeSplitDimInt but the output is an index in the original system and not in the simplified one */ unsigned int ComputeSplitDim(Tparameters *p,Tbox *b,TCuikSystem *cs) { Tbox bsimp; unsigned int d; if (!cs->scalar) Error("ComputeSplitDim only operates on scalar systems"); if (UpdateCuikSystem(p,cs)) { SimpleFromOriginal(b,&bsimp,cs->orig2sd); d=GetVarIDInOriginal(ComputeSplitDimInt(p,&bsimp,cs),cs->orig2sd); DeleteBox(&bsimp); } else d=NO_UINT; return(d); } /* Returns TRUE if point stored in vector 'v' is included in box 'b' Dummy variables are not taken into account in this procedure. */ boolean PointInSystemBox(Tvector *v,Tbox *b,TCuikSystem *cs) { unsigned int i,k,nv; double *val; boolean in; nv=NVariables(&(cs->orig_variables)); if (nv!=GetBoxNIntervals(b)) Error("Wrong box size in PointInSystemBox"); k=0; in=TRUE; for(i=0;((in)&&(i<nv));i++) { if (!IsDummyVariable(i,&(cs->orig_variables))) { val=(double *)GetVectorElement(k,v); if (val==NULL) Error("Vector with incorrect number of elements in PointInSystemBox"); in=IsInside(*val,0.0,GetBoxInterval(i,b)); k++; } } return(in); } void EvaluateCSEquations(double *p,double *r,TCuikSystem *cs) { EvaluateEqualityEquations(FALSE,p,r,&(cs->orig_equations)); } void EvaluateSimpCSEquations(Tparameters *pr,double *p,double *r,TCuikSystem *cs) { if (!UpdateCuikSystem(pr,cs)) Error("Inconsistent input cuiksystem"); EvaluateEqualityEquations(FALSE,p,r,&(cs->simp_equations)); } void EvaluateSubSetSimpCSEquations(Tparameters *pr,boolean *se,double *p,double *r,TCuikSystem *cs) { if (!UpdateCuikSystem(pr,cs)) Error("Inconsistent input cuiksystem"); EvaluateSubSetEqualityEquations(p,se,r,&(cs->simp_equations)); } void EvaluateCSJacobian(double *p,double ***J,TCuikSystem *cs) { TJacobian Ja; InitJacobian(&(cs->orig_variables),&(cs->orig_equations),&Ja); AllocateJacobianEvaluation(J,&Ja); EvaluateJacobian(p,*J,&Ja); DeleteJacobian(&Ja); } double ErrorInCSEquations(double *p,TCuikSystem *cs) { double *r,e; unsigned int neq; neq=NEqualityEquations(&(cs->orig_equations)); if (neq>0) { NEW(r,neq,double); EvaluateEqualityEquations(FALSE,p,r,&(cs->orig_equations)); e=Norm(neq,r); free(r); } else e=0.0; return(e); } double ErrorInSimpCSEquations(Tparameters *pr,double *p,TCuikSystem *cs) { double *r,e; unsigned int neq; if (!UpdateCuikSystem(pr,cs)) Error("Inconsistent input cuiksystem"); neq=NEqualityEquations(&(cs->simp_equations)); if (neq>0) { NEW(r,neq,double); EvaluateEqualityEquations(FALSE,p,r,&(cs->simp_equations)); e=Norm(neq,r); free(r); } else e=0.0; return(e); } double EvaluateCSCost(Tparameters *p,boolean simp,double *s,void *cs) { double v; if (simp) v=EvaluateWholeEquation(s,&(((TCuikSystem *)cs)->simp_eqMin)); else v=EvaluateWholeEquation(s,&(((TCuikSystem *)cs)->orig_eqMin)); return(v); } /* Takes the center of the box and computes the error of this point when replaced into the system of equations. We use this function to check the validity of the outputs of Cuik. */ double ErrorInSolution(Tbox *b,TCuikSystem *cs) { double *p; /*central point of the box*/ unsigned int i; double *r,maxError; //double e; unsigned int nv,neq; maxError=0; nv=NVariables(&(cs->orig_variables)); neq=NEqualityEquations(&(cs->orig_equations)); if ((nv>0)&&(neq>0)) { if (nv!=GetBoxNIntervals(b)) Error("Wrong box size in ErrorInSolution"); NEW(p,nv,double); for(i=0;i<nv;i++) p[i]=IntervalCenter(GetBoxInterval(i,b)); NEW(r,neq,double); EvaluateEqualityEquations(TRUE,p,r,&(cs->orig_equations)); maxError=Norm(neq,r); /* for(i=0;i<neq;i++) { e=fabs(r[i]); if (e>maxError) maxError=e; } */ free(r); free(p); } return(maxError); } double ErrorInInequalities(Tbox *b,TCuikSystem *cs) { unsigned int i,neq,nv; double maxError,*r,*p; nv=NVariables(&(cs->orig_variables)); if (nv!=GetBoxNIntervals(b)) Error("Wrong box size in ErrorInInequalities"); neq=NInequalityEquations(&(cs->orig_equations)); if (neq>0) { NEW(p,nv,double); for(i=0;i<cs->orig_nvariables;i++) p[i]=IntervalCenter(GetBoxInterval(i,b)); NEW(r,neq,double); EvaluateInequalityEquations(p,r,&(cs->orig_equations)); maxError=MaxVector(neq,r); free(r); free(p); } else maxError=0.0; return(maxError); } boolean InequalitiesHoldOnPoint(double *p,TCuikSystem *cs) { unsigned int neq; boolean hold; double *r; neq=NInequalityEquations(&(cs->orig_equations)); if (neq>0) { NEW(r,neq,double); EvaluateInequalityEquations(p,r,&(cs->orig_equations)); hold=(MaxVector(neq,r)==0.0); free(r); } else hold=TRUE; return(hold); } boolean SimpInequalitiesHoldOnPoint(Tparameters *pr,double *p,TCuikSystem *cs) { unsigned int neq; boolean hold; double *r; if (!UpdateCuikSystem(pr,cs)) Error("Inconsistent input cuiksystem"); neq=NInequalityEquations(&(cs->simp_equations)); if (neq>0) { NEW(r,neq,double); EvaluateInequalityEquations(p,r,&(cs->simp_equations)); hold=(MaxVector(neq,r)==0.0); free(r); } else hold=TRUE; return(hold); } double ErrorInSimpInequalitiesOnPoint(Tparameters *pr,double *p,TCuikSystem *cs) { unsigned int neq; double e,*r; if (!UpdateCuikSystem(pr,cs)) Error("Inconsistent input cuiksystem"); neq=NInequalityEquations(&(cs->simp_equations)); if (neq>0) { NEW(r,neq,double); EvaluateInequalityEquations(p,r,&(cs->simp_equations)); e=MaxVector(neq,r); free(r); } else e=0.0; return(e); } unsigned int ManifoldDimension(Tparameters *pr,double *p,TCuikSystem *cs) { double epsilon,*JT,error; double *pWithDummies,*pSimp; unsigned int nr,nc,k; if (!UpdateCuikSystem(pr,cs)) Error("Inconsistent cuiksystem in ComputeSplitDimInt"); if (cs->simp_nequations==0) Error("Empty simplified system in ManifoldDimension"); epsilon=GetParameter(CT_EPSILON,pr); /* Convert from original point ot simplified point */ RegenerateSolutionPoint(pr,p,&pWithDummies,cs); GenerateSimplifiedPoint(pr,pWithDummies,&pSimp,cs); /* We verify that the given point is a solution. Otherwise the rank estimation would be not valid. */ error=ErrorInSimpCSEquations(pr,pSimp,cs); if (error>epsilon) Error("Point not in manifold"); GetJacobianSize(&nr,&nc,&(cs->J)); if ((nr==0)||(nc==0)) Error("Empty jacobian in ManifoldDimension"); NEW(JT,nc*nr,double); EvaluateTransposedJacobianInVector(pSimp,nc,nr,JT,&(cs->J)); k=nc-FindRank(epsilon,nr,nc,JT); free(pWithDummies); free(pSimp); free(JT); return(k); } /* Prints the information stored in the cuiksystem It prints it in a form than can be parsed again. */ void PrintCuikSystem(Tparameters *p,FILE *f,TCuikSystem *cs) { unsigned int nv; char **varNames; PrintVariables(f,&(cs->orig_variables)); nv=NVariables(&(cs->orig_variables)); NEW(varNames,nv,char *); GetVariableNames(varNames,&(cs->orig_variables)); PrintEquations(f,varNames,&(cs->orig_equations)); if (cs->searchMode==MINIMIZATION_SEARCH) { fprintf(f,"\n[SEARCH]\n\n MIN "); PrintMonomials(f,varNames,&(cs->orig_eqMin)); } free(varNames); fprintf(f,"\n\n"); } /* Prints the information stored in the cuiksystem together with the simplified CuikSystem. It prints it in a form than can be parsed again. */ void PrintCuikSystemWithSimplification(Tparameters *p,FILE *f,TCuikSystem *cs) { unsigned int nv; char **varNames; #if (_DEBUG>1) fprintf(f,"%%****************************************\n"); fprintf(f,"%% Original system \n"); PrintVariables(f,&(cs->orig_variables)); nv=NVariables(&(cs->orig_variables)); NEW(varNames,nv,char *); GetVariableNames(varNames,&(cs->orig_variables)); PrintEquations(f,varNames,&(cs->orig_equations)); if (cs->searchMode==MINIMIZATION_SEARCH) { fprintf(f,"\n[SEARCH]\n\n MIN "); PrintMonomials(f,varNames,&(cs->orig_eqMin)); } fprintf(f,"\n\n"); free(varNames); #endif if (UpdateCuikSystem(p,cs)) { fprintf(f,"%%****************************************\n"); fprintf(f,"%% Simplified system \n"); fprintf(f,"%% SIMPLIFICATION_LEVEL: %u\n", (unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p))); fprintf(f,"%% Variable reduction %u -> %u\n",cs->orig_nvariables, cs->simp_nvariables); fprintf(f,"%% Num syst+secu variables in original : %u \n", GetNumSystemVariables(&(cs->orig_variables))+ GetNumSecondaryVariables(&(cs->orig_variables))); fprintf(f,"%% Num syst+secu variables in simplified: %u \n", GetNumSystemVariables(&(cs->simp_variables))+ GetNumSecondaryVariables(&(cs->simp_variables))); PrintMapping(f,cs->orig2sd); PrintVariables(f,&(cs->variables)); nv=NVariables(&(cs->variables)); NEW(varNames,nv,char *); GetVariableNames(varNames,&(cs->variables)); PrintEquations(f,varNames,&(cs->equations)); if (cs->searchMode==MINIMIZATION_SEARCH) { fprintf(f,"\n[SEARCH]\n\n MIN "); PrintMonomials(f,varNames,&(cs->eqMin)); } free(varNames); } else fprintf(f,"INCONSISTENT INPUT CUIK SYSTEM\n"); } void SaveCuikSystemSimplification(Tparameters *p,FILE *f,TCuikSystem *cs) { if (UpdateCuikSystem(p,cs)) SaveMapping(f,cs->orig2sd); else fprintf(f,"INCONSISTENT INPUT CUIK SYSTEM\n"); } /* Destructor of the cuiksystem structure. */ void DeleteCuikSystem(TCuikSystem *cs) { DeleteConstants(&(cs->constants)); DeleteVariables(&(cs->orig_variables)); DeleteEquations(&(cs->orig_equations)); DeleteStatistics(&(cs->st)); DeleteEquation(&(cs->orig_eqMin)); UnUpdateCuikSystem(cs); cs->empty=TRUE; cs->simp_empty=TRUE; }
1047 
1048  'c' is the return code out of Reduce Box
1049 
1050  If the box is small (max side size smaller than sigma), we consider it
1051  a solution and we store it in the list 'sol' (if defined), we save
1052  the solution into 'f_out' (if defined).
1053 
1054  Otherwise, we split the box in two sub-boxes and we store them in list 'boxes'
1055  The dimension along which the box is splitte is determined according to
1056  parameter 'error_split'. The two sub-boxes are added to 'boxes' in the first
1057  of in the last position according to parameter 'depth_first'.
1058 */
1060  unsigned int c,
1061  FILE *f_out,
1062  Tlist *sol,
1063  Theap *boxes,Tbox *b,
1064  TCuikSystem *cs)
1065 {
1066  boolean empty,small;
1067  Tbox b_orig;
1068  double sigma;
1069  unsigned int nNewton;
1070  double epsilon;
1071 
1072  empty=(c==EMPTY_BOX);
1073 
1074  if (empty)
1075  {
1076  NewEmptyBox(&(cs->st));
1077  #if (_DEBUG>1)
1078  printf(" The box is empty -> deleted\n");
1079  #endif
1080  #if (_DEBUG>0)
1081  fprintf(stderr,"e\n");
1082  #endif
1083  }
1084  else
1085  {
1086  /* c==REDUCED_BOX or c==REDUCED_BOX_WITH_SOLUTION or c==ERROR_IN_PROCESS*/
1087  #if (_DEBUG>1)
1088  printf(" Resulting box: ");
1089  PrintBox(stdout,b);
1090  #endif
1091  #if (_DEBUG>0)
1092  fprintf(stderr,"<%g %g>",
1093  GetBoxVolume(cs->systemVar,b),
1094  GetBoxSize(cs->systemVar,b));
1095  #endif
1096 
1097  /* We initialize a box in the original system and set the default ranges
1098  (ranges in case the variable in the original system is not in the
1099  simplified one... this is not likely to occur here but in the system
1100  to sybsystem relation but in this way the interface is the same)*/
1101  BoxFromVariables(&b_orig,&(cs->orig_variables));
1102  UpdateOriginalFromSimple(b,&b_orig,cs->orig2sd);
1103  #if (_DEBUG>1)
1104  printf(" Original box: ");
1105  PrintBox(stdout,&b_orig);
1106  #endif
1107 
1108  epsilon=GetParameter(CT_EPSILON,p);
1109 
1110  nNewton=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p);
1111  if ((nNewton>0)&&(f_out!=NULL)&&(GetBoxSize(cs->systemVar,b)>epsilon))
1112  {
1113  double *sol;
1114  Tbox b_sol;
1115 
1116  NEW(sol,cs->orig_nvariables,double);
1117 
1118  if ((CuikNewtonInBox(p,&b_orig,sol,&b_sol,cs)&(CONVERGED_IN_BOX|CONVERGED_IN_GLOBAL))>0)
1119  {
1120  fprintf(f_out,"Newton [s:%f v:%g l:%u t:%g]: ",
1121  GetBoxSize(cs->systemVar,b),
1122  GetBoxVolume(cs->systemVar,b),
1123  GetBoxLevel(b),
1124  GetElapsedTime(&(cs->st)));
1125  PrintBoxSubset(f_out,cs->orig_notDummyVar,cs->orig_varNames,&b_sol);
1126  }
1127 
1128  free(sol);
1129  DeleteBox(&b_sol);
1130  fflush(f_out);
1131  }
1132 
1133  sigma=GetParameter(CT_SIGMA,p);
1134 
1135  /*The original system can have variables not included in the simplified one. For instance,
1136  variables not in the system equations due to the particular constants of the problem under
1137  analysis are eliminated, even though they appear in dummy equations (this is common
1138  when ROT_REP=1, see link.h). Those removed variables are never reduced and thus,
1139  the original box never reduces below sigma. This is why we use the simplified box
1140  (i.e., the one we actually reduce) to assess whether or not we have a solution. */
1141  small=(GetBoxSize(cs->systemVar,b)<=sigma);
1142 
1143  if (small)
1144  {
1145  #if (_DEBUG>1)
1146  printf(" The box is a solution (size %g vs [%g]) ->add to the list of solutions\n",
1147  GetBoxSize(cs->orig_systemVar,&b_orig),sigma);
1148  #endif
1149 
1151  GetBoxVolume(cs->orig_systemVar,&b_orig),
1152  GetBoxDiagonal(cs->orig_systemVar,&b_orig),
1153  &(cs->st));
1154 
1155  if(c==ERROR_IN_PROCESS)
1156  NewRBError(&(cs->st));
1157 
1158  #if (_DEBUG>0)
1160  fprintf(stderr,"S\n");
1161  else
1162  fprintf(stderr,"s\n");
1163  #endif
1164 
1165 
1166  if (f_out!=NULL)
1167  {
1168  if(c==ERROR_IN_PROCESS)
1169  fprintf(f_out," E");
1170 
1171  fprintf(f_out," %3u (err:%g",
1172  GetNSolutionBoxes(&(cs->st)),
1173  ErrorInSolution(&b_orig,cs));
1174  #if (_DEBUG>1)
1175  printf(" Solution number %u with erorr %g\n",
1176  GetNSolutionBoxes(&(cs->st)),
1177  ErrorInSolution(&b_orig,cs));
1178  #endif
1179 
1181  fprintf(f_out," min:%g",EvaluateEqMin((void *)b,(void *)cs));
1182 
1183  fprintf(f_out," tm:%g):",GetElapsedTime(&(cs->st)));
1184 
1186  fprintf(f_out," <S> ");
1187 
1188  /*The output does not include the dummy variables (they are
1189  not relevant any more)*/
1190  PrintBoxSubset(f_out,cs->orig_notDummyVar,cs->orig_varNames,&b_orig);
1191  fflush(f_out);
1192  }
1193  if (sol!=NULL)
1194  {
1195  Tbox *sb;
1196 
1197  NEW(sb,1,Tbox);
1198 
1199  CopyBox(sb,&b_orig);
1200 
1201  AddLastElement((void *)sb,sol);
1202  }
1203 
1204  /*If we want to ad box to a solution list, we have to copy 'b'
1205  somewhere else ('b' is delete after this function !)*/
1206  }
1207  else
1208  {
1209  /* Non empty large box or error in ReduceBox */
1210 
1211  Tbox b1,b2;
1212  unsigned int d;
1213 
1214  #if (_DEBUG>1)
1215  printf(" Box size : %g vs. %g\n",GetBoxSize(cs->orig_systemVar,&b_orig),sigma);
1216  printf(" The box has to be splitted (and deleted)\n");
1217  #endif
1218 
1219  NewSplittedBox(&(cs->st));
1220 
1221  d=ComputeSplitDimInt(p,b,cs);
1222 
1223  SplitBox(d,CUT_POINT,&b1,&b2,b);
1224 
1225  #if (_DEBUG>1)
1226  printf(" Splitting along dimension %u (internal)\n",d);
1228  printf(" Box penalgy : %g\n",EvaluateEqMin((void *)&b1,(void *)cs));
1229  printf(" SubBox:"); PrintBox(stdout,&b1);
1231  printf(" Box penalty : %g\n",EvaluateEqMin((void *)&b2,(void *)cs));
1232  printf(" SubBox:"); PrintBox(stdout,&b2);
1233  #endif
1234 
1235  AddBox2HeapOfBoxes(&b1,boxes);
1236  AddBox2HeapOfBoxes(&b2,boxes);
1237  DeleteBox(&b1);
1238  DeleteBox(&b2);
1239 
1240  if (c==ERROR_IN_PROCESS)
1241  {
1242  #if (_DEBUG>0)
1243  fprintf(stderr,"E[%u]\n",d);
1244  #endif
1245  #if (_DEBUG>1)
1246  printf(" Splitted due to simplex error\n");
1247  #endif
1248  NewRBError(&(cs->st));
1249  }
1250  #if (_DEBUG>0)
1251  else
1252  fprintf(stderr,"b[%u]\n",d);
1253  #endif
1254  }
1255 
1256  DeleteBox(&b_orig);
1257  }
1258 }
1259 
1261 {
1262  unsigned int i,vt;
1263  double epsilon;
1264 
1265  epsilon=GetParameter(CT_EPSILON,p);
1266 
1267  /*We proceed back to front because removing a variable change the
1268  indexes of variables above it.*/
1269  i=NVariables(&(cs->variables));
1270  while(i>0)
1271  {
1272  i--;
1273  vt=GetVariableTypeN(i,&(cs->variables));
1274 
1275  if ((!VarIncluded(i,GetEquationVariables(&(cs->orig_eqMin))))&&
1276  (((vt==DUMMY_VAR)&&(!UsedVarInNonDummyEquations(i,&(cs->equations))))||
1277  ((vt!=SYSTEM_VAR)&&(!UsedVarInEquations(i,&(cs->equations))))))
1278  {
1279  /* ... Therefore, we can still have dummy equations with the non-used variables*/
1280  RemoveEquationsWithVar(epsilon,i,&(cs->equations));
1281  RemoveVariable(i,&(cs->variables));
1282  }
1283  }
1284 }
1285 
1287  boolean *replaced,TLinearConstraint *lc,
1288  Tbox *borig,TCuikSystem *cs)
1289 {
1290  boolean found,hold;
1291  unsigned int nv,origID1;
1292  unsigned int id1;
1293  char *name1;
1294  double epsilon;
1295  double ct2;
1296  Tinterval *range;
1297 
1298  epsilon=GetParameter(CT_EPSILON,p);
1299 
1300  hold=TRUE;
1301 
1302  do {
1303  found=FALSE;
1304 
1305  /* A variable with a ct range can be removed */
1306  nv=NVariables(&(cs->variables));
1307  id1=0;
1308  while((!found)&&(id1<nv))
1309  {
1310  name1=GetVariableName(GetVariable(id1,&(cs->variables)));
1311  origID1=GetVariableID(name1,&(cs->orig_variables));
1312  if (origID1==NO_UINT)
1313  Error("Undefined ID1 in CSRemoveVarsWithCtRange");
1314 
1315  range=GetBoxInterval(origID1,borig);
1316  if (IntervalSize(range)==0)
1317  {
1318  ct2=LowerLimit(range); /* ==UpperLimit(range) */
1319  found=TRUE;
1320  }
1321  else
1322  id1++;
1323  }
1324 
1325  /*if we found something to simplify, apply it to the rest of equations
1326  (this creates a new set of equations that replaces the previous one)*/
1327  if (found)
1328  {
1329  replaced[origID1]=TRUE;
1330  AddCt2LinearConstraint(ct2,&(lc[origID1]));
1331 
1332  #if (_DEBUG>5)
1333  printf("Ct Range Replacement: %s [%u-%u] ->%.12g\n",name1,origID1,id1,ct2);
1334  #endif
1335 
1336  if (hold)
1337  {
1338  TLinearConstraint lc;
1339 
1340  InitLinearConstraint(&lc);
1341  AddCt2LinearConstraint(ct2,&lc);
1342  hold=ReplaceVariableInEquations(epsilon,id1,&lc,&(cs->equations));
1344  RemoveVariable(id1,&(cs->variables));
1345 
1346  #if (_DEBUG>6)
1347  if(hold)
1348  {
1349  char **varNames;
1350 
1351 
1352  printf("%%=======================================================\n");
1353  printf("%% One less variable (ct range)\n");
1354  printf("%%****************************************\n");
1355  PrintVariables(stdout,&(cs->variables));
1356 
1357  nv=NVariables(&(cs->variables));
1358  NEW(varNames,nv,char *);
1359  GetVariableNames(varNames,&(cs->variables));
1360  PrintEquations(stdout,varNames,&(cs->equations));
1361  free(varNames);
1362  }
1363  #endif
1364  }
1365  }
1366  } while((hold)&&(found));
1367 
1368  return(hold);
1369 }
1370 
1371 boolean CSRemoveLCVars(Tparameters *p,unsigned int simplificationLevel,
1372  unsigned int nTerms,boolean *changed,
1373  boolean *replaced,TLinearConstraint *lc,
1374  Tbox *borig,TCuikSystem *cs)
1375 {
1376  boolean found,hold;
1377  unsigned int m,i,j,nv,neq,origID,origID1;
1378  Tequation *eq;
1379  unsigned int id;
1380  char *name,*name1;
1381  double epsilon;
1382  Tvariable *v;
1383  TLinearConstraint lcr,lcc;
1384  boolean *systemVars;
1385  Tinterval error;
1386  Tbox currentBox;
1387  boolean polynomial;
1388  #if (_DEBUG>5)
1389  char **varNamesO;
1390 
1391  nv=NVariables(&(cs->orig_variables));
1392  NEW(varNamesO,nv,char *);
1393  GetVariableNames(varNamesO,&(cs->orig_variables));
1394  #endif
1395  polynomial=PolynomialEquations(&(cs->orig_equations));
1396  nv=NVariables(&(cs->variables));
1397  InitBox(nv,NULL,&currentBox);
1398  NEW(systemVars,nv,boolean);
1399  for(i=0;i<nv;i++)
1400  {
1401  systemVars[i]=IsSystemVariable(i,&(cs->variables));
1402  SetBoxInterval(i,GetVariableInterval(GetVariable(i,&(cs->variables))),&currentBox);
1403  }
1404 
1405  epsilon=GetParameter(CT_EPSILON,p);
1406 
1407  *changed=FALSE;
1408  hold=TRUE;
1409 
1410  /* Only scalar equations can be used to generate simplifcation */
1411  found=FALSE;
1412  i=0;
1413  neq=NScalarEquations(&(cs->equations));
1414  while((!found)&&(i<neq))
1415  {
1416  eq=GetScalarEquation(i,&(cs->equations));
1417  found=IsSimplificable(simplificationLevel,nTerms,((cs->scalar)&&(polynomial)),
1418  systemVars,&currentBox,&id,&lcr,eq); /* 't' is the type of simplification*/
1419  if (!found)
1420  i++;
1421  }
1422  DeleteBox(&currentBox);
1423 
1424  /*if we found something to simplify, apply it to the rest of equations
1425  (this creates a new set of equations that replaces the previous one)*/
1426  if (found)
1427  {
1428  *changed=TRUE;
1429 
1430  /* Translate the variables identifiers from local to global */
1431  v=GetVariable(id,&(cs->variables));
1432  name=GetVariableName(v);
1433  origID=GetVariableID(name,&(cs->orig_variables));
1434  if (origID==NO_UINT)
1435  Error("Undefined var in original system in CSRemoveLCVars");
1436 
1437  /* Translate the 'lcr' linear constraint that refers to the cuiksystem
1438  in the current state of simplification to the original system */
1440  for(i=0;i<m;i++)
1441  {
1443  name1=GetVariableName(v);
1444  origID1=GetVariableID(name1,&(cs->orig_variables));
1445  if (origID1==NO_UINT)
1446  Error("Undefined variable in original system in CSRemoveLCVars");
1447  AddTerm2LinearConstraint(origID1,
1449  &(lc[origID]));
1450  }
1451  GetLinearConstraintError(&error,&lcr);
1452  if (IntervalSize(&error)>ZERO)
1453  Error("Linear constraint used for variable replacement must have ct right-hand");
1454  AddCt2LinearConstraint(-IntervalCenter(&error),&(lc[origID]));
1455 
1456  replaced[origID]=TRUE;
1457 
1458  #if (_DEBUG>5)
1459  printf("Var Replacement: %s[%u-%u]->",name,origID,id);
1460  PrintLinearConstraint(stdout,FALSE,varNamesO,&(lc[origID]));
1461  #endif
1462 
1463  CopyLinearConstraint(&lcc,&(lc[origID]));
1464  AddTerm2LinearConstraint(origID,-1.0,&lcc);
1465  hold=CropLinearConstraint(ZERO,ANY_TYPE_VAR,borig,&(cs->orig_variables),&lcc);
1466  if (!hold)
1467  printf("\nNon intersecting ranges (I)\n");
1468  DeleteLinearConstraint(&lcc);
1469 
1470  /*If origID was used for the replacement of another variable
1471  we have to propagate the replacement of origID1 to this other
1472  variable*/
1473  nv=NVariables(&(cs->orig_variables));
1474  for(j=0;((hold)&&(j<nv));j++)
1475  {
1476  if ((replaced[j])&&(LinearConstraintIncludes(origID,&(lc[j]))))
1477  {
1478  TLinearConstraint ltmp;
1479  double ct;
1480 
1481  ct=RemoveTermFromLinearConstraint(origID,&(lc[j]));
1482  CopyLinearConstraint(&ltmp,&(lc[origID]));
1483  ScaleLinearConstraint(ct,&ltmp);
1484  AddLinearConstraints(&ltmp,&(lc[j]));
1485  DeleteLinearConstraint(&ltmp);
1486 
1487  CopyLinearConstraint(&lcc,&(lc[j]));
1488  AddTerm2LinearConstraint(j,-1.0,&lcc);
1489  hold=CropLinearConstraint(ZERO,ANY_TYPE_VAR,borig,&(cs->orig_variables),&lcc);
1490  if (!hold)
1491  printf("\nNon intersecting ranges (II)\n");
1492  DeleteLinearConstraint(&lcc);
1493  }
1494  }
1495 
1496  if (hold)
1497  {
1498  hold=ReplaceVariableInEquations(epsilon,id,&lcr,&(cs->equations));
1499  RemoveVariable(id,&(cs->variables));
1500 
1501  #if (_DEBUG>6)
1502  if(hold)
1503  {
1504  char **varNames;
1505 
1506  printf("%%=======================================================\n");
1507  printf("%% One less variable (replaced)\n");
1508  printf("%%****************************************\n");
1509  PrintVariables(stdout,&(cs->variables));
1510 
1511  nv=NVariables(&(cs->variables));
1512  NEW(varNames,nv,char *);
1513  GetVariableNames(varNames,&(cs->variables));
1514  PrintEquations(stdout,varNames,&(cs->equations));
1515  free(varNames);
1516  }
1517  #endif
1518  }
1519 
1520  DeleteLinearConstraint(&lcr);
1521  }
1522  #if (_DEBUG>5)
1523  free(varNamesO);
1524  #endif
1525  free(systemVars);
1526  return(hold);
1527 }
1528 
1529 /*
1530  Simplifies a CuikSystem removing variables have constant value and those
1531  that depend linearly on other variables. Moreover, a primitive (but numerically
1532  save) form of Gaussian elimination is performed to remove as more variables
1533  and equations as possible.
1534  More elaborate forms of system simplifications are not implemented because they
1535  result in numerical errors (that can change the system solutions).
1536  The output mappings give information about how the original and the simplified
1537  systems are related.
1538 
1539  This is part of the UpdateCuikSystem.
1540 */
1542 {
1543  unsigned int i,nv,nvn,newVarID;
1544  boolean *replaced;
1545  TLinearConstraint *lc,lcS;
1546  boolean changed,anyChange,hold;
1547  char *name1;
1548  Tbox borig,bsimp;
1549  unsigned int nTerms,m,k;
1550  Tinterval error;
1551  unsigned int simplificationLevel;
1552 
1553  simplificationLevel=(unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p));
1554 
1555  /* Matrix equations or non-polynomial equations -> at most variable replacement */
1556  if ((!cs->scalar)||((!PolynomialEquations(&(cs->orig_equations)))&&(simplificationLevel>1)))
1557  simplificationLevel=(simplificationLevel>2?2:simplificationLevel);
1558 
1559  #if (_DEBUG>6)
1560  {
1561  char **varNames;
1562 
1563  printf("%%=======================================================\n");
1564  printf("%% Original system\n");
1565  printf("%%****************************************\n");
1566  PrintVariables(stdout,&(cs->orig_variables));
1567 
1568  nv=NVariables(&(cs->orig_variables));
1569  NEW(varNames,nv,char *);
1570  GetVariableNames(varNames,&(cs->orig_variables));
1571  PrintEquations(stdout,varNames,&(cs->orig_equations));
1572  free(varNames);
1573  }
1574  #endif
1575 
1576 
1577  /* Get a copy of the original cuiksystem */
1578  CopyVariables(&(cs->variables),&(cs->orig_variables));
1579  CopyEquations(&(cs->equations),&(cs->orig_equations));
1580 
1581  nv=NVariables(&(cs->orig_variables)); /* number of variables in the original system */
1582 
1583  NEW(replaced,nv,boolean);
1584  NEW(lc,nv,TLinearConstraint);
1585 
1586  BoxFromVariables(&borig,&(cs->orig_variables)); /*original ranges to be possibly reduced during
1587  simplification */
1588  for(i=0;i<nv;i++)
1589  {
1590  replaced[i]=FALSE;
1591  InitLinearConstraint(&(lc[i]));
1592  }
1593 
1594  hold=TRUE; /* in the simplification process we can discover that the input system
1595  is inconsitent (i.e., that it does not hold)*/
1596 
1597  CSRemoveUnusedVars(p,cs); /* This is done even without simplification */
1598 
1599  if (simplificationLevel>0) /* For detailed debug, systems are not simplified */
1600  {
1601  hold=CSRemoveVarsWithCtRange(p,replaced,lc,&borig,cs);
1602 
1603  anyChange=TRUE; /* Set to TRUE to trigger the simplification process */
1604  while((hold)&&(anyChange))
1605  {
1606  anyChange=FALSE; /* Will be set to TRUE if at least one variable is removed
1607  in the loop below */
1608  nTerms=0; /* First we try to remove ct variables, then scaled ones,i.e., we
1609  progressivelly increase the number of terms used in the
1610  replacements. */
1611  while((hold)&&(nTerms<=MAX_TERMS_SIMP)) /*hard-coded maximum complexity of the simplifications*/
1612  {
1613  hold=CSRemoveLCVars(p,simplificationLevel,nTerms,&changed,replaced,lc,&borig,cs);
1614  anyChange=((anyChange)||(changed));
1615  if (changed)
1616  nTerms=0;
1617  else
1618  nTerms++;
1619  }
1620 
1621  /* At this point no more ct or scaled varibles can be removed. Try to
1622  simplify the problem via Gaussian elimination*/
1623  if ((hold)&&(anyChange))
1624  {
1625  anyChange=FALSE;
1626  do {
1627  changed=GaussianElimination(&(cs->equations));
1628  anyChange=((anyChange)||(changed));
1629  } while (changed);
1630 
1631  #if (_DEBUG>6)
1632  {
1633  char **varNames;
1634  unsigned int nvg;
1635 
1636  printf("%%=======================================================\n");
1637  printf("%% After gaussian elimination\n");
1638  printf("%%****************************************\n");
1639  PrintVariables(stdout,&(cs->variables));
1640 
1641  nvg=NVariables(&(cs->variables));
1642  NEW(varNames,nvg,char *);
1643  GetVariableNames(varNames,&(cs->variables));
1644  PrintEquations(stdout,varNames,&(cs->equations));
1645  free(varNames);
1646  }
1647  #endif
1648  }
1649  }
1650  }
1651 
1652  #if(_DEBUG>4)
1653  if (hold)
1654  {
1655  char **varNames;
1656  unsigned int nvg;
1657 
1658  printf("%%=======================================================\n");
1659  printf("%%FINAL SIMPLIFIED SYSTEM\n");
1660  printf("%%****************************************\n");
1661  PrintVariables(stdout,&(cs->variables));
1662 
1663  nvg=NVariables(&(cs->variables));
1664  NEW(varNames,nvg,char *);
1665  GetVariableNames(varNames,&(cs->variables));
1666  PrintEquations(stdout,varNames,&(cs->equations));
1667  free(varNames);
1668  }
1669  else
1670  printf("Inconsistent input system\n");
1671  #endif
1672 
1673  if (hold)
1674  {
1675  /* Get a copy of the simplified but not still dummified cuiksystem */
1676  CopyVariables(&(cs->simp_variables),&(cs->variables));
1677  CopyEquations(&(cs->simp_equations),&(cs->equations));
1678 
1679  /*The final step is to dummify the cuiksystem*/
1680  DummifyCuikSystem(p,cs);
1681 
1682  /* Cache information in the simplified equations just
1683  in case we want to efficiently evalute its equalities.
1684  This is done, for instance, in the (cuik)gradient */
1686 
1687  /*define the mappings from the gathered information*/
1688 
1689  NEW(cs->orig2sd,1,Tmapping);
1690  NEW(cs->orig2s,1,Tmapping);
1691 
1692  InitMapping(&(cs->orig_variables),&(cs->variables),cs->orig2sd);
1693  InitMapping(&(cs->orig_variables),&(cs->simp_variables),cs->orig2s);
1694 
1695  /* now we complement the default initialization with the replacements computed above */
1696  for(i=0;i<nv;i++)
1697  {
1698  if (replaced[i])
1699  {
1700  m=GetNumTermsInLinearConstraint(&(lc[i]));
1701  InitLinearConstraint(&lcS);
1702  for(k=0;k<m;k++)
1703  {
1705  newVarID=GetVariableID(name1,&(cs->variables));
1706 
1707  AddTerm2LinearConstraint(newVarID,GetLinearConstraintCoefficient(k,&(lc[i])),&lcS);
1708  }
1709  GetLinearConstraintError(&error,&(lc[i]));
1710  AddCt2LinearConstraint(-IntervalCenter(&error),&lcS);
1711 
1712  SetOriginalVarRelation(i,&lcS,cs->orig2sd);
1713  SetOriginalVarRelation(i,&lcS,cs->orig2s);
1714 
1715  DeleteLinearConstraint(&lcS);
1716  }
1717  }
1718 
1719  #if(_DEBUG>4)
1720  if (hold)
1721  {
1722  char **varNames;
1723  unsigned int nvg;
1724 
1725  printf("%%=======================================================\n");
1726  printf("%%FINAL final SIMPLIFIED SYSTEM\n");
1727  printf("%%****************************************\n");
1728  PrintVariables(stdout,&(cs->variables));
1729 
1730  nvg=NVariables(&(cs->variables));
1731  NEW(varNames,nvg,char *);
1732  GetVariableNames(varNames,&(cs->variables));
1733  PrintEquations(stdout,varNames,&(cs->equations));
1734  free(varNames);
1735  }
1736  else
1737  printf("Inconsistent input system\n");
1738  #endif
1739 
1740  SimpleFromOriginal(&borig,&bsimp,cs->orig2s);
1741  nvn=NVariables(&(cs->simp_variables));
1742  for(i=0;i<nvn;i++)
1744  DeleteBox(&bsimp);
1745 
1746  SimpleFromOriginal(&borig,&bsimp,cs->orig2sd);
1747  nvn=NVariables(&(cs->variables));
1748  for(i=0;i<nvn;i++)
1750  DeleteBox(&bsimp);
1751  }
1752 
1753  DeleteBox(&borig);
1754 
1755  /* free the information used for the mapping */
1756  for(i=0;i<nv;i++)
1757  DeleteLinearConstraint(&lc[i]);
1758  free(replaced);
1759  free(lc);
1760 
1761  return(hold);
1762 }
1763 
1764 /*
1765  Removes the information stored in the cuiksystem during the update
1766 */
1768 {
1769 
1770  if (cs->updated)
1771  {
1772  /*Removes cached information that is used during solving*/
1773 
1774  /*Firt the box sorting information*/
1776  {
1777  DeleteEquation(&(cs->eqMin));
1778  DeleteEquation(&(cs->simp_eqMin));
1779  }
1780 
1781 
1782  /*Now the information about the simplified+dummified system*/
1783  if (cs->orig2sd!=NULL)
1784  {
1785  DeleteMapping(cs->orig2sd);
1786  free(cs->orig2sd);
1787  cs->orig2sd=NULL;
1788  }
1789 
1790  cs->nequations=0;
1791  cs->nvariables=0;
1792  if (cs->systemVar!=NULL)
1793  free(cs->systemVar);
1794  cs->systemVar=NULL;
1795  if (cs->notDummyVar!=NULL)
1796  free(cs->notDummyVar);
1797  cs->notDummyVar=NULL;
1798  if (cs->varType!=NULL)
1799  free(cs->varType);
1800  cs->varType=NULL;
1801 
1802  DeleteEquations(&(cs->equations));
1803  DeleteVariables(&(cs->variables));
1804 
1805  /*Now remove the information about the simplified system*/
1806  if (cs->orig2s!=NULL)
1807  {
1808  DeleteMapping(cs->orig2s);
1809  free(cs->orig2s);
1810  cs->orig2s=NULL;
1811  }
1812 
1813  if (cs->simp_nequations>0)
1814  DeleteJacobian(&(cs->J));
1815 
1816  cs->simp_nequations=0;
1817  cs->simp_nvariables=0;;
1818  cs->simp_nee=0;
1819 
1822 
1823  if (cs->simp_tp!=NULL)
1824  free(cs->simp_tp);
1825 
1826  /*Finally remove the information about the original system*/
1827  cs->orig_nequations=0;
1828  cs->orig_nvariables=0;
1829  if (cs->orig_systemVar!=NULL)
1830  free(cs->orig_systemVar);
1831  cs->orig_systemVar=NULL;
1832  if (cs->orig_notDummyVar!=NULL)
1833  free(cs->orig_notDummyVar);
1834  cs->orig_notDummyVar=NULL;
1835 
1836  free(cs->orig_varNames);
1837  cs->orig_varNames=NULL;
1838 
1839  /*Mark the system as not updated*/
1840  cs->updated=FALSE;
1841 
1842  /*We assume the system to be consistent although this value is not
1843  used unless cs->update is TRUE*/
1844  cs->consistent=TRUE;
1845  }
1846 }
1847 
1848 /*
1849  Simplifies the CuikSystem and caches information that is useful during
1850  solving (cached->faster access).
1851 */
1853 {
1854  if (!cs->updated)
1855  {
1856  unsigned int j;
1857  boolean found;
1858 
1859  /* we update even if we have no equations to be able to deal
1860  with systems without equations (non constrained problems)
1861  In this case cuik is a standard approximated cell decomposition
1862  approach
1863  */
1864  cs->consistent=SimplifyCuikSystem(p,cs);
1865 
1866  if (cs->consistent)
1867  {
1868  /* Update the information in the original system */
1871 
1872  if ((cs->orig_nequations>0)&&(cs->orig_nvariables==0))
1873  Error("System with equations but without variables");
1874 
1875  if (cs->orig_nvariables==0)
1876  {
1877  cs->orig_systemVar=NULL;
1878  cs->orig_notDummyVar=NULL;
1879  cs->orig_varNames=NULL;
1880  }
1881  else
1882  {
1883  NEW(cs->orig_systemVar,cs->orig_nvariables,boolean);
1884  NEW(cs->orig_notDummyVar,cs->orig_nvariables,boolean);
1885 
1886  /* Note that orig_systemVar include the secodary variables while
1887  systemVar (the one for the simplified/dummified system) keeps
1888  the difference between system and secondary varibles */
1889  for(j=0;j<cs->orig_nvariables;j++)
1890  {
1891  cs->orig_systemVar[j]=((IsSystemVariable(j,&(cs->orig_variables)))||
1892  (IsSecondaryVariable(j,&(cs->orig_variables))));
1894  }
1895 
1896  NEW(cs->orig_varNames,cs->orig_nvariables,char *);
1898  }
1899 
1900  /* Update the simplifed cuiksystem */
1904  cs->simp_empty=((cs->simp_nvariables==0)&&(cs->simp_nequations==0));
1905 
1906  if (cs->simp_empty)
1907  cs->simp_tp=NULL;
1908  else
1909  {
1911  found=FALSE;
1912  j=0;
1913  while ((!found)&&(j<cs->simp_nvariables))
1914  {
1915  found=(cs->simp_tp[j]!=TOPOLOGY_R);
1916  j++;
1917  }
1918  if (!found)
1919  {
1920  free(cs->simp_tp);
1921  cs->simp_tp=NULL;
1922  }
1923  }
1924 
1925  if (cs->simp_nequations>0)
1926  InitJacobian(&(cs->simp_variables),&(cs->simp_equations),&(cs->J));
1927 
1928  /* Update the information in the simplified+dummified cuiksystem*/
1929  cs->nequations=NEquations(&(cs->equations));
1930  cs->nvariables=NVariables(&(cs->variables));
1931  cs->empty=((cs->nvariables==0)||(cs->nequations==0));
1932 
1933  if (cs->nvariables==0)
1934  {
1935  cs->systemVar=NULL;
1936  cs->notDummyVar=NULL;
1937  cs->varType=NULL;
1938  }
1939  else
1940  {
1941  NEW(cs->systemVar,cs->nvariables,boolean);
1942  NEW(cs->notDummyVar,cs->nvariables,boolean);
1943  NEW(cs->varType,cs->nvariables,unsigned int);
1944 
1945  for(j=0;j<cs->nvariables;j++)
1946  {
1947  cs->systemVar[j]=IsSystemVariable(j,&(cs->variables));
1948  cs->notDummyVar[j]=!IsDummyVariable(j,&(cs->variables));
1949  cs->varType[j]=GetVariableTypeN(j,&(cs->variables));
1950  }
1951  }
1952 
1953  /* Update the information about the sorting criteria for boxes */
1955  {
1956  if (GetNumMonomials(&(cs->orig_eqMin))==0)
1957  {
1958  ResetEquation(&(cs->orig_eqMin));
1960  }
1961  else
1962  {
1964  cs->orig2sd,&(cs->eqMin),&(cs->orig_eqMin));
1966  cs->orig2s,&(cs->simp_eqMin),&(cs->orig_eqMin));
1967  }
1968  }
1969 
1970  /* Mark the system as updated )(althogh it might not be consistent) */
1971  cs->updated=TRUE;
1972  }
1973  }
1974 
1975  return(cs->consistent);
1976 }
1977 
1978 /*
1979  Selects one dimension along which to split box 'b'. The dimension can
1980  be selected according to the size or according to the error that each
1981  variable induce in each equation.
1982  The output is a index in the simplified system
1983  */
1985 {
1986 
1987  if (!UpdateCuikSystem(p,cs))
1988  Error("Inconsistent cuiksystem in ComputeSplitDimInt");
1989 
1990  if (cs->nvariables==0)
1991  {
1992  Error("Splitting an empty cuiksystem");
1993  return(NO_UINT);
1994  }
1995  else
1996  {
1997  unsigned int i;
1998  Tinterval *is;
1999  double *splitDim;
2000  unsigned int *d;
2001  unsigned int n;
2002  double m,s;
2003  unsigned int splitType;
2004  double epsilon;
2005 
2006  epsilon=GetParameter(CT_EPSILON,p);
2007  splitType=(unsigned int)(GetParameter(CT_SPLIT_TYPE,p));
2008 
2009  NEW(splitDim,cs->nvariables,double);
2010  NEW(d,cs->nvariables,unsigned int);
2011 
2012  is=GetBoxIntervals(b);
2013 
2014  if ((cs->nequations>0)&&(splitType==1))
2015  {
2016  for(i=0;i<cs->nvariables;i++)
2017  splitDim[i]=0.0;
2018 
2019  /*Add the error contribution*/
2020  for(i=0;i<cs->nequations;i++)
2021  UpdateSplitWeight(i,splitDim,b,&(cs->equations));
2022 
2023  /*Do not split along unbounded or too small variables*/
2024  for(i=0;i<cs->nvariables;i++)
2025  {
2026  s=IntervalSize(&(is[i]));
2027  if ((s<10*epsilon)||(s>=INF))
2028  splitDim[i]=0.0;
2029  }
2030  }
2031  else
2032  {
2033  if (splitType!=2)
2034  {
2035  /*size-based split or error-based split without any equation*/
2036 
2037  for(i=0;i<cs->nvariables;i++)
2038  {
2039  s=IntervalSize(&(is[i]));
2040  if (s<INF)
2041  splitDim[i]=s;
2042  else
2043  splitDim[i]=0.0;
2044  }
2045  }
2046  else
2047  {
2048  /*splitType==2 -> random selection of the split dimension */
2049  for(i=0;i<cs->nvariables;i++)
2050  {
2051  s=IntervalSize(&(is[i]));
2052  if ((s>10*epsilon)&&(s<INF))
2053  splitDim[i]=1.0;
2054  else
2055  splitDim[i]=0.0;
2056  }
2057 
2058  }
2059  }
2060 
2061  m=-1.0;
2062  n=0;
2063  for(i=0;i<cs->nvariables;i++)
2064  {
2065  if (cs->systemVar[i])
2066  {
2067  if (splitDim[i]>m)
2068  {
2069  m=splitDim[i];
2070  d[0]=i;
2071  n=1;
2072  }
2073  else
2074  {
2075  if (splitDim[i]==m)
2076  {
2077  d[n]=i;
2078  n++;
2079  }
2080  }
2081  }
2082  }
2083 
2084  if (n>0)
2085  {
2086  #if (RANDOMNESS)
2087  i=d[randomMax(n-1)];
2088  #else
2089  i=d[0];
2090  #endif
2091  }
2092  else
2093  {
2094  Warning("There is no way where to bisect the box");
2095  i=randomMax(cs->nvariables-1);
2096  }
2097 
2098  free(d);
2099  free(splitDim);
2100 
2101  return(i);
2102  }
2103 }
2104 
2105 void SaveCSState(char *fname,Tlist *lb,TCuikSystem *cs)
2106 {
2107  FILE *f;
2108  char *tmpName;
2109  double tm;
2110 
2111  /*We initially save to a temporary file and then we rename it
2112  This increases the atomiticy of this operation (if the state
2113  file is corrupted the recovery operation would fail) */
2114  NEW(tmpName,strlen(fname)+10,char);
2115  sprintf(tmpName,"%s.tmp",fname);
2116 
2117  /*open in binary mode*/
2118  f=fopen(tmpName,"wb");
2119  if (!f)
2120  Error("Could not open file for saving CSState");
2121 
2122  tm=GetElapsedTime(&(cs->st));
2123  fwrite(&tm,sizeof(double),1,f);
2124  SaveStatistics(f,&(cs->st));
2125  SaveListOfBoxes(f,lb);
2126 
2127  fclose(f);
2128 
2129  remove(fname);
2130  rename(tmpName,fname);
2131  free(tmpName);
2132 }
2133 
2134 void LoadCSState(char *fname,Tlist *lb,TCuikSystem *cs)
2135 {
2136  FILE *f;
2137  double tm;
2138  Titerator it;
2139 
2140  f=fopen(fname,"rb");
2141  if (!f)
2142  Error("Could not open file for loading CSState");
2143 
2144  fread(&tm,sizeof(double),1,f);
2145  LoadStatistics(f,&(cs->st));
2146  LoadListOfBoxes(f,lb);
2147 
2148  fclose(f);
2149 
2150  InitIterator(&it,lb);
2151  First(&it);
2152  if (cs->nvariables!=GetBoxNIntervals((Tbox *)GetCurrent(&it)))
2153  Error("The saved .state and the problem dimensionality do not match");
2154 
2155  /*Pretend that the process was started tm seconds before now*/
2156  SetInitialTime(GetTime(&(cs->st))-tm,&(cs->st));
2157 }
2158 
2159 
2160 /************************************************************************/
2161 /************************************************************************/
2162 /************************************************************************/
2163 
2164 /*
2165  Warms up the cuiksystem structure
2166 */
2168 {
2169  InitConstants(&(cs->constants));
2170 
2171  InitVariables(&(cs->orig_variables));
2172  InitEquations(&(cs->orig_equations));
2173 
2174  /* cs->variables and cs->equations are initialized
2175  via Copy when simplifying the system*/
2176  cs->empty=TRUE;
2177  cs->simp_empty=TRUE;
2178 
2179  cs->updated=FALSE;
2180  cs->consistent=TRUE; /*this is not used unless updated=TRUE*/
2181 
2182  cs->scalar=TRUE;
2183 
2184  cs->nequations=0;
2185  cs->nvariables=0;
2186 
2187  cs->systemVar=NULL;
2188  cs->notDummyVar=NULL;
2189  cs->varType=NULL;
2190 
2191  cs->orig2sd=NULL;
2192 
2193  cs->orig2s=NULL;
2194  cs->simp_tp=NULL;
2195 
2196  cs->orig_nequations=0;
2197  cs->orig_nvariables=0;
2198 
2199  cs->orig_systemVar=NULL;
2200  cs->orig_notDummyVar=NULL;
2201 
2203  InitEquation(&(cs->orig_eqMin));
2204 }
2205 
2207 {
2208  if (!UpdateCuikSystem(p,cs))
2209  Error("Inconsistent input cuiksystem");
2210 }
2211 
2212 /*
2213  Copies one cuiksystem structure into another (that is assumed as
2214  initialized but empty).
2215 */
2217 {
2218  CopyConstants(&(cs_dst->constants),&(cs_src->constants));
2219 
2220  cs_dst->updated=cs_src->updated;
2221  cs_dst->consistent=cs_src->consistent;
2222  cs_dst->empty=cs_src->empty;
2223  cs_dst->scalar=cs_src->scalar;
2224 
2225  CopyStatistics(&(cs_dst->st),&(cs_src->st));
2226 
2227  cs_dst->searchMode=cs_src->searchMode;
2228  CopyEquation(&(cs_dst->orig_eqMin),&(cs_src->orig_eqMin));
2229 
2230  CopyEquations(&(cs_dst->orig_equations),&(cs_src->orig_equations));
2231  CopyVariables(&(cs_dst->orig_variables),&(cs_src->orig_variables));
2232 
2233  if (cs_dst->updated)
2234  {
2235  /*The simplified dummified system*/
2236  NEW(cs_dst->orig2sd,1,Tmapping);
2237  CopyMapping(cs_dst->orig2sd,cs_src->orig2sd);
2238 
2239  CopyEquations(&(cs_dst->equations),&(cs_src->equations));
2240  CopyVariables(&(cs_dst->variables),&(cs_src->variables));
2241 
2242  cs_dst->nequations=cs_src->nequations;
2243  cs_dst->nvariables=cs_src->nvariables;
2244 
2245  if (cs_dst->nvariables==0)
2246  {
2247  cs_dst->systemVar=NULL;
2248  cs_dst->notDummyVar=NULL;
2249  cs_dst->varType=NULL;
2250  }
2251  else
2252  {
2253  NEW(cs_dst->systemVar,cs_dst->nvariables,boolean);
2254  memcpy(cs_dst->systemVar,cs_src->systemVar,sizeof(boolean)*cs_dst->nvariables);
2255 
2256  NEW(cs_dst->notDummyVar,cs_dst->nvariables,boolean);
2257  memcpy(cs_dst->notDummyVar,cs_src->notDummyVar,sizeof(boolean)*cs_dst->nvariables);
2258 
2259  NEW(cs_dst->varType,cs_dst->nvariables,unsigned int);
2260  memcpy(cs_dst->varType,cs_src->varType,sizeof(unsigned int)*cs_dst->nvariables);
2261  }
2262 
2263  if (cs_dst->searchMode==MINIMIZATION_SEARCH)
2264  {
2265  CopyEquation(&(cs_dst->eqMin),&(cs_src->eqMin));
2266  CopyEquation(&(cs_dst->simp_eqMin),&(cs_src->simp_eqMin));
2267  }
2268 
2269 
2270  /*The simplified system*/
2271  NEW(cs_dst->orig2s,1,Tmapping);
2272  CopyMapping(cs_dst->orig2s,cs_src->orig2s);
2273 
2274  cs_dst->simp_empty=cs_src->simp_empty;
2275 
2276  CopyEquations(&(cs_dst->simp_equations),&(cs_src->simp_equations));
2277  CopyVariables(&(cs_dst->simp_variables),&(cs_src->simp_variables));
2278 
2279  cs_dst->simp_nequations=cs_src->simp_nequations;
2280  cs_dst->simp_nvariables=cs_src->simp_nvariables;
2281  cs_dst->simp_nee=cs_src->simp_nee;
2282 
2283  if (cs_src->simp_tp!=NULL)
2284  {
2285  NEW(cs_dst->simp_tp,cs_dst->simp_nvariables,unsigned int);
2286  memcpy(cs_dst->simp_tp,cs_src->simp_tp,sizeof(unsigned int)*cs_dst->simp_nvariables);
2287  }
2288  else
2289  cs_dst->simp_tp=NULL;
2290 
2291  CopyJacobian(&(cs_dst->J),&(cs_src->J));
2292 
2293  /*Cached elements from the original system*/
2294  cs_dst->orig_nequations=cs_src->orig_nequations;
2295  cs_dst->orig_nvariables=cs_src->orig_nvariables;
2296 
2297  if (cs_dst->orig_nvariables==0)
2298  {
2299  cs_dst->orig_systemVar=NULL;
2300  cs_dst->orig_notDummyVar=NULL;
2301  cs_dst->orig_varNames=NULL;
2302  }
2303  else
2304  {
2305  NEW(cs_dst->orig_systemVar,cs_dst->orig_nvariables,boolean);
2306  memcpy(cs_dst->orig_systemVar,cs_src->orig_systemVar,cs_dst->orig_nvariables*sizeof(boolean));
2307 
2308  NEW(cs_dst->orig_notDummyVar,cs_dst->orig_nvariables,boolean);
2309  memcpy(cs_dst->orig_notDummyVar,cs_src->orig_notDummyVar,cs_dst->orig_nvariables*sizeof(boolean));
2310 
2311  NEW(cs_dst->orig_varNames,cs_dst->orig_nvariables,char *);
2312  GetVariableNames(cs_dst->orig_varNames,&(cs_dst->orig_variables));
2313  }
2314  }
2315  else
2316  {
2317  cs_dst->orig2sd=NULL;
2318  cs_dst->orig2s=NULL;
2319 
2320  cs_dst->nequations=0;
2321  cs_dst->nvariables=0;
2322  cs_dst->systemVar=NULL;
2323  cs_dst->notDummyVar=NULL;
2324  cs_dst->varType=NULL;
2325  cs_dst->simp_tp=NULL;
2326 
2327  cs_dst->orig_nequations=0;
2328  cs_dst->orig_nvariables=0;
2329  cs_dst->orig_systemVar=NULL;
2330  cs_dst->orig_notDummyVar=NULL;
2331  cs_dst->orig_varNames=NULL;
2332  }
2333 }
2334 
2336 {
2337  unsigned int nvar1,nvar2;
2338  unsigned int i;
2339 
2340  InitCuikSystem(cs);
2341 
2342  MergeConstants(&(cs1->constants),&(cs2->constants),&(cs->constants));
2343 
2344  cs->empty=((cs1->empty)&&(cs2->empty));
2345  cs->simp_empty=((cs1->simp_empty)&&(cs2->simp_empty));
2346 
2347  cs->updated=FALSE;
2348  cs->consistent=TRUE; /*not used untill updated==TRUE*/
2349 
2350  cs->scalar=((ScalarEquations(&(cs1->orig_equations)))&&
2351  (ScalarEquations(&(cs->orig_equations))));
2352 
2353  cs->orig2sd=NULL;
2354 
2355  cs->nequations=0;
2356  cs->nvariables=0;
2357  cs->systemVar=NULL;
2358  cs->notDummyVar=NULL;
2359  cs->varType=NULL;
2360 
2361  cs->orig_nequations=0;
2362  cs->orig_nvariables=0;
2363  cs->orig_systemVar=NULL;
2364  cs->orig_notDummyVar=NULL;
2365 
2366  /* One of the sets of variables is supposed to be a sub-set of the
2367  other.
2368  If nvar1 is larger than the larger set was in cs1 and nothing has
2369  to be done*/
2371  nvar1=NVariables(&(cs1->orig_variables));
2372  nvar2=NVariables(&(cs2->orig_variables));
2373  for(i=nvar1;i<nvar2;i++)
2374  AddVariable2CS(GetVariable(i,&(cs2->orig_variables)),cs);
2375 
2378 
2379  cs->searchMode=cs1->searchMode;
2380  CopyEquation(&(cs->orig_eqMin),&(cs1->orig_eqMin));
2381  AccumulateEquations(&(cs2->orig_eqMin),1,&(cs->orig_eqMin));
2382 }
2383 
2384 double EvaluateEqMin(void *b,void *cs)
2385 {
2386  double v=0;
2387 
2388  if (!((TCuikSystem *)cs)->updated)
2389  Error("The CuikSystem must be updated before using EvaluateEqMin");
2390 
2391  if (!((TCuikSystem *)cs)->consistent)
2392  Error("The CuikSystem must be consistent before using EvaluateEqMin");
2393 
2394  if (((TCuikSystem *)cs)->searchMode==MINIMIZATION_SEARCH)
2395  {
2396  #if (EQ_MIN_IN_CENTER)
2397  unsigned int nv;
2398  double *p;
2399  unsigned int i;
2400 
2401  nv=NVariables(&(((TCuikSystem *)cs)->variables));
2402 
2403  NEW(p,nv,double);
2404 
2405  for(i=0;i<nv;i++)
2406  p[i]=IntervalCenter(GetBoxInterval(i,(Tbox *)b));
2407 
2408  v=EvaluateWholeEquation(p,&(((TCuikSystem *)cs)->eqMin));
2409 
2410  free(p);
2411  #else
2412  Tinterval ie;
2413  double ct;
2414 
2415  ct=GetEquationValue(&(((TCuikSystem *)cs)->eqMin));
2416 
2417  EvaluateEquationInt(GetBoxIntervals((Tbox *)b),&ie,&(((TCuikSystem *)cs)->eqMin));
2418  IntervalOffset(&ie,-ct,&ie);
2419 
2420  /*v=LowerLimit(&ie);*/
2421  /*v=UpperLimit(&ie);*/
2422  v=IntervalCenter(&ie);
2423  #endif
2424  }
2425  return(v);
2426 }
2427 
2428 boolean CmpBoxesEquation(void *b1,void *b2,void *cs)
2429 {
2430  return(EvaluateEqMin(b1,cs)<EvaluateEqMin(b2,cs));
2431 }
2432 
2433 void SetCSSearchMode(unsigned int sm,Tequation *eqMin,TCuikSystem *cs)
2434 {
2435  if (cs->updated)
2436  UnUpdateCuikSystem(cs);
2437 
2438  switch(sm)
2439  {
2440  case DEPTH_FIRST_SEARCH:
2442  break;
2443  case BREADTH_FIRST_SEARCH:
2445  break;
2446  case MINIMIZATION_SEARCH:
2448  DeleteEquation(&(cs->orig_eqMin));
2449  CopyEquation(&(cs->orig_eqMin),eqMin);
2450  break;
2451  default:
2452  Error("Unkonwn search mode in SetCSSearchMode");
2453  }
2454 }
2455 
2456 void AddTerm2SearchCriterion(double w,unsigned int v,double val,TCuikSystem *cs)
2457 {
2458  if (w!=0.0)
2459  {
2460  Tequation eq;
2461  Tmonomial m;
2462 
2463  if (cs->updated)
2464  UnUpdateCuikSystem(cs);
2465 
2466  InitEquation(&eq);
2467  SetEquationCmp(EQU,&eq);
2468  InitMonomial(&m);
2469 
2470  AddCt2Monomial(w,&m);
2471  AddVariable2Monomial(NFUN,v,2,&m);
2472  AddMonomial(&m,&eq);
2473  ResetMonomial(&m);
2474 
2475  AddCt2Monomial(-w*2*val,&m);
2476  AddVariable2Monomial(NFUN,v,1,&m);
2477  AddMonomial(&m,&eq);
2478  ResetMonomial(&m);
2479 
2480  AddCt2Monomial(w*val*val,&m);
2481  AddMonomial(&m,&eq);
2482  ResetMonomial(&m);
2483 
2485  AccumulateEquations(&eq,1,&(cs->orig_eqMin));
2486  else
2488 
2489  DeleteMonomial(&m);
2490  DeleteEquation(&eq);
2491  }
2492 }
2493 
2494 /*
2495  Adds a equation to the CuikSystem.
2496  Equations as added by the user are not dummified. This helps
2497  when simplifying the system (dummify variables can prevent some
2498  simplifications or make them more "obscure")
2499  The dummificitaion is applied after the simplification of the
2500  system (see SimplifyCuikSystem)
2501 */
2503 {
2504  if (cs->updated)
2505  UnUpdateCuikSystem(cs);
2506 
2507  if (eq!=NULL)
2508  AddEquation(eq,&(cs->orig_equations));
2509 }
2510 
2512 {
2513  if (cs->updated)
2514  UnUpdateCuikSystem(cs);
2515 
2516  if (eq!=NULL)
2517  {
2518  cs->scalar=FALSE;
2519  if (!SimplifiedMEquation(eq))
2520  Error("Adding a non-simplified matrix equation to the cuiksystem");
2521  //SimplifyMEquation(eq);
2522  AddMatrixEquation(eq,&(cs->orig_equations));
2523  }
2524 }
2525 
2526 
2527 /*
2528  Checks if the system has a variable with the given name.
2529  If so, we return the variable identifier.
2530  If not, we create a new variable
2531  */
2533 {
2534  unsigned int id;
2535 
2536  if (cs->updated)
2537  UnUpdateCuikSystem(cs);
2538 
2540 
2541  if (id==NO_UINT)
2542  id=AddVariable(v,&(cs->orig_variables));
2543 
2544  return(id);
2545 }
2546 
2547 /*
2548  Returns a copy of the variables stored in the CuikSystem
2549 */
2551 {
2552  CopyVariables(vs,&(cs->orig_variables));
2553 }
2554 
2555 void GetCSVariableNames(char **varNames,TCuikSystem *cs)
2556 {
2557  /* We do not use the cached orig_varnames since the cs
2558  can be non-updated */
2559  GetVariableNames(varNames,&(cs->orig_variables));
2560 }
2561 
2562 /*
2563  Returns the number of variables in the CuikSystem
2564 */
2566 {
2567  return(NVariables(&(cs->orig_variables)));
2568 }
2569 
2571 {
2572  return(GetNumSystemVariables(&(cs->orig_variables))+
2574 }
2575 
2576 /*
2577  Returns the number of system variables in the CuikSystem
2578 */
2580 {
2582 }
2583 
2584 /*
2585  Gets a copy of variable with ID 'n'
2586 */
2587 void GetCSVariable(unsigned int n,Tvariable *v,TCuikSystem *cs)
2588 {
2590 }
2591 
2592 /*
2593  Sets a new range for variable with ID 'n'
2594 */
2595 void SetCSVariableRange(unsigned int n,Tinterval *r,TCuikSystem *cs)
2596 {
2597  if (cs->updated)
2598  UnUpdateCuikSystem(cs); /* Variables with ct range are simplified in
2599  the UpdateCuikSystem */
2600 
2602 }
2603 
2604 /*
2605  Gets the ID of the variable with the given name
2606 */
2607 unsigned int GetCSVariableID(char *name,TCuikSystem *cs)
2608 {
2609  return(GetVariableID(name,&(cs->orig_variables)));
2610 }
2611 
2612 char *GetCSVariableName(unsigned int id,TCuikSystem *cs)
2613 {
2614  return(VariableName(id,&(cs->orig_variables)));
2615 }
2616 
2617 char *GetCSSystemVariableName(unsigned int id,TCuikSystem *cs)
2618 {
2619  unsigned int i,n,k;
2620  boolean found;
2621  char *name=NULL;
2622 
2623  n=NVariables(&(cs->orig_variables));
2624 
2625  k=0;
2626  found=FALSE;
2627  for(i=0;((!found)&&(i<n));i++)
2628  if ((IsSystemVariable(i,&(cs->orig_variables)))||
2629  (IsSecondaryVariable(i,&(cs->orig_variables))))
2630  {
2631  if (k==id)
2632  {
2633  name=VariableName(i,&(cs->orig_variables));
2634  found=TRUE;
2635  }
2636  k++;
2637  }
2638  return(name);
2639 }
2640 
2642 {
2643  unsigned int n;
2644 
2645  if (!UpdateCuikSystem(p,cs))
2646  Error("Inconsistent input cuiksystem");
2647 
2648  n=GetVariableID(v,&(cs->simp_variables));
2649  return((n!=NO_UINT)&&
2650  ((IsSystemVariable(n,&(cs->simp_variables)))||
2651  (IsSecondaryVariable(n,&(cs->simp_variables)))));
2652 }
2653 
2654 /*
2655  Returns an array of booleans with sv[i]=TRUE if variable
2656  'i' is a system variable.
2657  Also returns the number of variables in the CuikSystem
2658 */
2659 unsigned int GetCSSystemVars(boolean **sv,TCuikSystem *cs)
2660 {
2661  unsigned int i,n;
2662 
2663  n=NVariables(&(cs->orig_variables));
2664  NEW(*sv,n,boolean);
2665 
2666  for(i=0;i<n;i++)
2667  (*sv)[i]=((IsSystemVariable(i,&(cs->orig_variables)))||
2668  (IsSecondaryVariable(i,&(cs->orig_variables))));
2669  return(n);
2670 }
2671 
2672 unsigned int GetCSVarTopology(unsigned int vID,TCuikSystem *cs)
2673 {
2674  return(GetVariableTopology(GetVariable(vID,&(cs->orig_variables))));
2675 }
2676 
2677 /*
2678  Returns a copy of the equations in the cuiksystem
2679 */
2681 {
2682  CopyEquations(eqs,&(cs->orig_equations));
2683 }
2684 
2685 /*
2686  Returns a copy of equation 'n' in the CuikSystem
2687 */
2688 void GetCSEquation(unsigned int n,Tequation *eq,TCuikSystem *cs)
2689 {
2690  if (!cs->scalar)
2691  Error("GetCSEquation only operates on scalar systems");
2692 
2693  CopyEquation(eq,GetEquation(n,&(cs->orig_equations)));
2694 }
2695 
2697 {
2698  return(PolynomialEquations(&(cs->orig_equations)));
2699 }
2700 
2702 {
2703  return(cs->scalar);
2704 }
2705 
2706 /*
2707  Returns the number of equations in the CuikSytem
2708 */
2710 {
2711  return(NEquations(&(cs->orig_equations)));
2712 }
2713 
2715 {
2716  InitJacobian(&(cs->orig_variables),&(cs->orig_equations),J);
2717 }
2718 
2720  unsigned int **t,TCuikSystem *cs)
2721 {
2722  if (!UpdateCuikSystem(p,cs))
2723  Error("Inconsistent input cuiksystem");
2724 
2725  return(GetVariablesTopology(t,&(cs->simp_variables)));
2726 }
2727 
2728 unsigned int GetCSTopology(Tparameters *p,
2729  unsigned int **t,TCuikSystem *cs)
2730 {
2731  return(GetVariablesTopology(t,&(cs->orig_variables)));
2732 }
2733 
2735 {
2736 
2737  if (!UpdateCuikSystem(p,cs))
2738  Error("Inconsistent input cuiksystem");
2739  InitJacobian(&(cs->simp_variables),&(cs->simp_equations),J);
2740 }
2741 
2742 void AddJacobianEquationsInt(Tparameters *p,boolean *selectedVars,TJacobian *J,
2743  TCuikSystem *cs)
2744 {
2745  Tinterval one_one,zero_one;
2746  unsigned int *nvl;
2747  Tvariable v;
2748  char vname[100];
2749  Tequation eq,eq1;
2750  unsigned int i,j,nvars,neqs;
2751 
2752  if (!cs->scalar)
2753  Error("AddJacobianEquationsInt only operates on scalar systems");
2754 
2755  GetJacobianSize(&neqs,&nvars,J);
2756 
2757  NewInterval(-1.0,1.0,&one_one);
2758  NewInterval( 0.0,1.0,&zero_one);
2759 
2760  /* From this point we start to modify cs and thus, all
2761  queries to the original cs must be done on csOrig*/
2762 
2763  /*define the lambda variables*/
2764  NEW(nvl,neqs,unsigned int);
2765  for(i=0;i<neqs;i++)
2766  {
2767  sprintf(vname,"_lambda_%u",i);
2768  NewVariable(SYSTEM_VAR,vname,&v);
2769  SetVariableInterval((i==0?&zero_one:&one_one),&v);
2770 
2771  nvl[i]=AddVariable2CS(&v,cs);
2772 
2773  DeleteVariable(&v);
2774  }
2775 
2776  /*Lambdas must be normalized*/
2777  GenerateGeneralNormEquation(neqs,nvl,1.0,&eq);
2778  AddEquation2CS(p,&eq,cs);
2779  DeleteEquation(&eq);
2780 
2781  /*define the linear combination using the lambda*/
2782  for(j=0;j<nvars;j++)
2783  {
2784  if ((selectedVars==NULL)||(selectedVars[j]))
2785  {
2786  InitEquation(&eq);
2787  SetEquationCmp(EQU,&eq);
2789 
2790  for(i=0;i<neqs;i++)
2791  {
2792  CopyEquation(&eq1,GetJacobianEquation(i,j,J));
2793  VarScaleEquation(nvl[i],&eq1);
2794  AccumulateEquations(&eq1,1.0,&eq);
2795  DeleteEquation(&eq1);
2796  }
2797 
2798  AddEquation2CS(p,&eq,cs);
2799  DeleteEquation(&eq);
2800  }
2801  }
2802 }
2803 
2804 
2805 void AddJacobianEquations(Tparameters *p,boolean *selectedVars,TCuikSystem *cs)
2806 {
2807  unsigned int neqs,nvars,i,ns;
2808  TCuikSystem csOrig;
2809  TJacobian J;
2810 
2811  if (!UpdateCuikSystem(p,cs))
2812  Error("Inconsistent input cuiksystem");
2813 
2814  CopyCuikSystem(&csOrig,cs);
2815  GetCSJacobian(&J,&csOrig);
2816  GetJacobianSize(&neqs,&nvars,&J);
2817 
2818  if (selectedVars==NULL)
2819  ns=nvars;
2820  else
2821  {
2822  ns=0;
2823  for(i=0;i<nvars;i++)
2824  if (selectedVars[i]) ns++;
2825  }
2826 
2827  if ((neqs>0)&&(ns>0))
2828  AddJacobianEquationsInt(p,selectedVars,&J,cs);
2829 
2830  DeleteJacobian(&J);
2831  UnUpdateCuikSystem(cs);
2832  DeleteCuikSystem(&csOrig);
2833 }
2834 
2835 void AddSimplifiedJacobianEquations(Tparameters *p,boolean *selectedVars,TCuikSystem *cs)
2836 {
2837  unsigned int neqs,nvars,i,ns;
2838  boolean *simpSelectedVars;
2839  unsigned int simpID,nt;
2840  TLinearConstraint lc;
2841  TCuikSystem csOrig;
2842 
2843  if (!cs->scalar)
2844  Error("AddSimplifiedJacobianEquations only operates on scalar systems");
2845 
2846  if (!UpdateCuikSystem(p,cs))
2847  Error("Inconsistent input cuiksystem");
2848 
2849  CopyCuikSystem(&csOrig,cs);
2850 
2851  neqs=cs->simp_nee;
2852  nvars=cs->simp_nvariables;
2853 
2854  NEW(simpSelectedVars,nvars,boolean);
2855  if (selectedVars==NULL)
2856  ns=nvars;
2857  else
2858  {
2859  /*Translated the selected vars from original to simplified*/
2860  for(i=0;i<nvars;i++)
2861  simpSelectedVars[i]=TRUE;
2862 
2863  ns=0;
2864  for(i=0;i<cs->orig_nvariables;i++)
2865  {
2866  if (!selectedVars[i])
2867  {
2868  GetOriginalVarRelation(i,&lc,cs->orig2s);
2870  /* if nt is zero the variable is set to constant
2871  and must be not taken into account*/
2872  if (nt>0)
2873  {
2874  ns++;
2875  /*We use the first variable in the simplified
2876  system as equivalent to the original variable*/
2877  simpID=GetLinearConstraintVariable(0,&lc);
2878  simpSelectedVars[simpID]=FALSE;
2879  #if (_DEBUG>0)
2880  printf(" Var %s -> %s\n",cs->orig_varNames[i],
2881  VariableName(simpID,&(cs->simp_variables)));
2882  #endif
2883  }
2884  #if (_DEBUG>0)
2885  else
2886  printf(" Var %s -> constant (not considered)\n",cs->orig_varNames[i]);
2887  #endif
2889  }
2890  }
2891  }
2892 
2893  if ((neqs>0)&&(ns>0))
2894  {
2895  TJacobian J;
2896  Tequation *eq;
2897  unsigned int j;
2898 
2899  /* We have to translate the simplified Jacobian matrix to the original system */
2900  InitJacobian(&(csOrig.simp_variables),&(csOrig.simp_equations),&J);
2901 
2902  for(i=0;i<neqs;i++)
2903  {
2904  for(j=0;j<nvars;j++)
2905  {
2906  eq=GetJacobianEquation(i,j,&J);
2907  RewriteEquation2Orig(csOrig.orig2s,eq,eq);
2908  }
2909  }
2910 
2911  #if (_DEBUG>1)
2912  {
2913  char **varNames;
2914 
2915  NEW(varNames,csOrig.orig_nvariables,char*);
2916  GetVariableNames(varNames,&(csOrig.orig_variables));
2917  for(j=0;j<nvars;j++)
2918  {
2919  for(i=0;i<neqs;i++)
2920  {
2921  printf("J[%u,%u] ->",i,j);
2922  PrintEquation(stdout,varNames,GetJacobianEquation(i,j,&J));
2923  }
2924  }
2925  free(varNames);
2926  }
2927  #endif
2928 
2929  AddJacobianEquationsInt(p,simpSelectedVars,&J,cs);
2930 
2931  DeleteJacobian(&J);
2932  }
2933 
2934  UnUpdateCuikSystem(cs);
2935  DeleteCuikSystem(&csOrig);
2936 }
2937 
2938 /*
2939  Reduces a box as much as possible (according to parameters in 'p').
2940  If the set of parameters is undefined, we use a default set.
2941  This procedure is used in CuikPlan.
2942 
2943  This is basically another flavor of ReduceBox where parameters
2944  are given in one structure instead of as different inputs
2945 
2946  The input box and output boxes are refered to the original
2947  cuiksystem (the non-simplified one)
2948 
2949  The output can be EMPTY_BOX
2950  REDUCED_BOX
2951  REDUCED_BOX_WITH_SOLUTION
2952  ERROR_IN_PROCESS
2953 
2954 */
2955 unsigned int MaxReduction(Tparameters *p,unsigned int varMask,double *reduction,Tbox *b,TCuikSystem *cs)
2956 {
2957  unsigned int e;
2958 
2959  if (!cs->scalar)
2960  Error("MaxReduction only operates on scalar systems");
2961 
2962  if (UpdateCuikSystem(p,cs))
2963  {
2964  Tbox bsimp;
2965  double sIn,sOut;
2966 
2967  SimpleFromOriginal(b,&bsimp,cs->orig2sd);
2968  sIn=GetBoxSize(cs->systemVar,&bsimp);
2969  e=ReduceBox(p,(varMask==0?~DUMMY_VAR:varMask),&bsimp,cs);
2970  if (e==EMPTY_BOX)
2971  *reduction=0;
2972  else
2973  {
2974  sOut=GetBoxSize(cs->systemVar,&bsimp);
2975  *reduction=sOut/sIn;
2976  /* ERROR_IN_PROCESS, REDUCED_BOX, REDUCED_BOX_WITH_SOLUTION*/
2977  UpdateOriginalFromSimple(&bsimp,b,cs->orig2sd);
2978  }
2979  DeleteBox(&bsimp);
2980  }
2981  else
2982  e=EMPTY_BOX;
2983 
2984  return(e);
2985 }
2986 
2987 
2988 boolean SampleCuikSystem(Tparameters *p,char *fname,Tlist *sb,
2989  unsigned int nsamples,unsigned int ntries,
2990  unsigned int ndof,TCuikSystem *cs)
2991 {
2992  Tbox init_box;
2993  boolean haveSample;
2994 
2995  if (!cs->scalar)
2996  Error("SampleCuikSystem only operates on scalar systems");
2997 
2998  GenerateInitialBox(&init_box,cs);
2999 
3000  haveSample=SampleCuikSystemInBox(p,fname,sb,nsamples,ntries,ndof,&init_box,cs);
3001 
3002  DeleteBox(&init_box);
3003 
3004  return(haveSample);
3005 }
3006 
3007 boolean SampleCuikSystemInBox(Tparameters *p,char *fname,Tlist *sb,
3008  unsigned int nsamples,unsigned int ntries,
3009  unsigned int ndof,
3010  Tbox *init_box,TCuikSystem *cs)
3011 {
3012  Tbox orig_ranges,b,*bAux,*box;
3013  Tlist solutions;
3014  unsigned int k,d,ns,nv,ne,i,nt;
3015  double v;
3016 
3017  Tfilename fsols_box;
3018  Tfilename fsols_point;
3019 
3020  FILE *f_out_box;
3021  FILE *f_out_point;
3022 
3023  Titerator it;
3024  boolean *systemVars;
3025  Tinterval *r;
3026  unsigned int spt;
3027  double ms;
3028  double reduction;
3029 
3030  boolean ok;
3031  boolean end;
3032 
3033  /* free var = variable not in equations -> must be fixed always */
3034  unsigned int *freeVars;
3035  unsigned int nFreeVars;
3036 
3037  unsigned int nsols;
3038 
3039  if (!cs->scalar)
3040  Error("SampleCuikSystemInBox only operates on scalar systems");
3041 
3042  /*Get a copy of the ranges in 'cs' for all the variables*/
3043  GenerateInitialBox(&orig_ranges,cs);
3044 
3045  /*Set the ranges for the 'cs' variables to those in the given box (init_box)*/
3046  if (cs->updated)
3047  UnUpdateCuikSystem(cs);
3048 
3049  nv=NVariables(&(cs->orig_variables));
3050  for(k=0;k<nv;k++)
3052 
3053  NEW(freeVars,nv,unsigned int);
3054  nFreeVars=0;
3055  for(k=0;k<nv;k++)
3056  {
3057  if ((GetVariableTypeN(k,&(cs->orig_variables))==SYSTEM_VAR)&&
3058  (!UsedVarInEquations(k,&(cs->orig_equations))))
3059  {
3060  freeVars[nFreeVars]=k;
3061  nFreeVars++;
3062  }
3063  }
3064 
3065  /*Change the SPLIT_TYPE parameter to random split*/
3066  spt=(unsigned int)GetParameter(CT_SPLIT_TYPE,p);
3067  ChangeParameter(CT_SPLIT_TYPE,2,p); /* select split dimentions at random */
3068  /*Change the SMALL_SIGMA parameter to ensure it is small enough.
3069  SMALL_SIGMA controls the precission of the isolated solutions and, thus, of the
3070  sampled points. */
3073  /*keep the original nsols parameter*/
3074  nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p);
3075 
3076  if (fname==NULL)
3077  {
3078  f_out_box=NULL;
3079  f_out_point=NULL;
3080  }
3081  else
3082  {
3083  /* Check if we can create the output files */
3084  CreateFileName(NULL,fname,"_samples",SOL_EXT,&fsols_box);
3085  f_out_box=fopen(GetFileFullName(&fsols_box),"w");
3086  if (!f_out_box)
3087  Error("Could not open box sample output file");
3088 
3089  CreateFileName(NULL,fname,NULL,LINKS_EXT,&fsols_point);
3090  f_out_point=fopen(GetFileFullName(&fsols_point),"w");
3091  if (!f_out_point)
3092  Error("Could not open box sample output file");
3093  }
3094 
3095  if (sb!=NULL)
3096  InitListOfBoxes(sb);
3097 
3098  nv=GetCSNumVariables(cs);
3099  ne=GetCSNumEquations(cs);
3100 
3101  if (ndof==NO_UINT)
3102  {
3103  /* try to get the number of dof from the system (vars-equations) */
3104  if (ne>=nv)
3105  Error("Over/Well-constrained system. Please indicate the number of dof in the call");
3106  ndof=nv-ne;
3107  }
3108 
3109  if (MaxReduction(p,~DUMMY_VAR,&reduction,init_box,cs)==EMPTY_BOX)
3110  end=TRUE;
3111  else
3112  end=FALSE;
3113 
3114  if (nFreeVars>ndof)
3115  Error("More free vars than degrees of freedom");
3116 
3117  ns=0; /*samples already determined*/
3118  nt=0; /*number of tries so far*/
3119  while(!end)
3120  {
3121  do {
3122  ok=TRUE;
3123 
3124  /*fix 'ndof' variables*/
3125  CopyBox(&b,init_box);
3126  for(k=0;k<nv;k++)
3127  SetCSVariableRange(k,GetBoxInterval(k,&b),cs);
3128 
3129  for(k=0;k<nFreeVars;k++)
3130  {
3131  r=GetBoxInterval(freeVars[k],&b);
3132  v=randomInInterval(r);
3133 
3134  #if (_DEBUG>1)
3135  printf("[CS]->fixing %u to %f\n",freeVars[k],v);
3136  #endif
3137 
3138  NewInterval(v,v,r);
3139 
3140  SetCSVariableRange(freeVars[k],r,cs);
3141  }
3142 
3143  for(k=nFreeVars;((ok)&&(k<ndof));k++)
3144  {
3145  /*fix 'ndof' variables*/
3146 
3147  /* This updates the system, including simplification */
3148  d=ComputeSplitDim(p,&b,cs);
3149 
3150  if (d==NO_UINT)
3151  ok=FALSE;
3152  else
3153  {
3154  r=GetBoxInterval(d,&b);
3155  v=randomInInterval(r);
3156 
3157  #if (_DEBUG>1)
3158  printf("[CS]->fixing %u to %f\n",d,v);
3159  #endif
3160 
3161  NewInterval(v,v,r);
3162 
3163  SetCSVariableRange(d,r,cs);
3164  }
3165  }
3166 
3167  #if (_DEBUG>1)
3168  if (ok)
3169  {printf("[CS]");PrintBox(stdout,&b);}
3170  else
3171  printf("Inconsistent system while sampling\n");
3172  #endif
3173 
3174  DeleteBox(&b);
3175 
3176  nt++;
3177  if ((ntries!=NO_UINT)&&(nt==ntries))
3178  end=TRUE;
3179  } while((!ok)&&(!end));
3180 
3181  if (!end)
3182  {
3183 
3184  InitListOfBoxes(&solutions);
3185 
3186  /*See if there are solutions for the fixed ranges*/
3187  ChangeParameter(CT_N_SOLUTIONS,nsamples-ns,p);
3188  SolveCuikSystem(p,FALSE,NULL,NULL,f_out_box,&solutions,cs);
3189 
3190  /*We have to print the samples*/
3191  GetCSSystemVars(&systemVars,cs);
3192  InitIterator(&it,&solutions);
3193  First(&it);
3194  while((!EndOfList(&it))&&(!end))
3195  {
3196  bAux=(Tbox *)GetCurrent(&it);
3197 
3198  if (f_out_point!=NULL)
3199  {
3200  /* Print the center of the box into the point file */
3201  /* We only print values for the system vars */
3202  for(i=0;i<nv;i++)
3203  {
3204  if (systemVars[i])
3205  fprintf(f_out_point," %.12g",IntervalCenter(GetBoxInterval(i,bAux)));
3206  }
3207  fprintf(f_out_point,"\n");
3208  }
3209  if (sb!=NULL)
3210  {
3211  NEW(box,1,Tbox);
3212 
3213  CopyBox(box,bAux);
3214 
3215  AddLastElement((void *)box,sb);
3216  }
3217 
3218  ns++;
3219  if (ns<nsamples)
3220  end=TRUE;
3221  Advance(&it);
3222  }
3223  free(systemVars);
3224 
3225  fflush(f_out_point);
3226  fflush(f_out_box);
3227 
3228  /*Remove all boxes from the list and the current box*/
3229  DeleteListOfBoxes(&solutions);
3230  }
3231  }
3232 
3233  if (f_out_box!=NULL)
3234  {
3235  DeleteFileName(&fsols_box);
3236  fclose(f_out_box);
3237  }
3238  if (f_out_point!=NULL)
3239  {
3240  fclose(f_out_point);
3241  DeleteFileName(&fsols_point);
3242  }
3243 
3244  /*Restore the user given split_type, min_sigma, and n_solutions*/
3248 
3249  /*Return the original ranges to the 'cs' variables*/
3250  if (cs->updated)
3251  UnUpdateCuikSystem(cs);
3252 
3253  nv=NVariables(&(cs->orig_variables));
3254  for(k=0;k<nv;k++)
3255  SetVariableInterval(GetBoxInterval(k,&orig_ranges),GetVariable(k,&(cs->orig_variables)));
3256 
3257  free(freeVars);
3258 
3259  DeleteBox(&orig_ranges);
3260 
3261  return(!end);
3262 }
3263 
3264 
3265 boolean IncrementalSampleCuikSystem(Tparameters *p,char *fname,Tlist *sb,
3266  boolean *fixVars,
3267  unsigned int nsamples,unsigned int ntries,
3268  unsigned int ndof,TCuikSystem *cs)
3269 {
3270  Tbox init_box;
3271  boolean haveSample;
3272 
3273  if (!cs->scalar)
3274  Error("IncrementalSampleCuikSystem only operates on scalar systems");
3275 
3276  GenerateInitialBox(&init_box,cs);
3277 
3278  haveSample=IncrementalSampleCuikSystemInBox(p,fname,sb,fixVars,nsamples,ntries,ndof,&init_box,cs);
3279 
3280  DeleteBox(&init_box);
3281 
3282  return(haveSample);
3283 }
3284 
3286  boolean *fixVars,
3287  unsigned int nsamples,unsigned int ntries,
3288  unsigned int ndof,
3289  Tbox *init_box,TCuikSystem *cs)
3290 {
3291  Tbox b,*bAux,*box;
3292  Tlist solutions;
3293  unsigned int k,d,ns,nv,ne,i,nt;
3294  double v;
3295 
3296  double smallSigma;
3297 
3298  Tfilename fsols_box;
3299  Tfilename fsols_point;
3300 
3301  FILE *f_out_box;
3302  FILE *f_out_point;
3303 
3304  Titerator it;
3305  boolean *systemVars;
3306  Tinterval *r,newr;
3307  Tbox *bl;
3308  double ms;
3309  double reduction;
3310 
3311  boolean ok;
3312  boolean end;
3313 
3314  boolean *fv;
3315  unsigned int *ind2fv;
3316  unsigned int nfv;
3317  unsigned int newtonIterations;
3318  double *sol;
3319  Tbox b_sol;
3320  Tbox orig_ranges;
3321  unsigned int level,*attempts,maxAttemptsPerLevel;
3322  unsigned int nsols;
3323 
3324  if (!cs->scalar)
3325  Error("IncrementalSampleCuikSystemInBox only operates on scalar systems");
3326 
3327  /*Set the ranges for the 'cs' variables to those in the given box (init_box)*/
3328 
3329  if (!UpdateCuikSystem(p,cs))
3330  Error("Inconsistent cuiksystem in IncrementalSampleCuikSystemInBox");
3331 
3332  BoxFromVariables(&orig_ranges,&(cs->orig_variables));
3333 
3334  nv=NVariables(&(cs->orig_variables));
3335 
3336  NEW(sol,nv,double);
3337 
3339  smallSigma=100*GetParameter(CT_EPSILON,p);
3340  ChangeParameter(CT_SMALL_SIGMA,smallSigma,p);
3341 
3342  nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p);
3343 
3344  newtonIterations=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p);
3345 
3346  /* Array of variables that can be fixed */
3347  NEW(fv,nv,boolean);
3348  NEW(ind2fv,nv,unsigned int);
3349  nfv=0;
3350  for(k=0;k<nv;k++)
3351  {
3352  if ((IntervalSize(GetBoxInterval(k,init_box))>smallSigma)&&
3353  (IsInSimple(k,cs->orig2sd)))
3354  {
3355  if (((fixVars!=NULL)&&(fixVars[k]))||
3356  ((fixVars==NULL)&&(IsSystemVariable(k,&(cs->orig_variables)))))
3357  {
3358  fv[k]=TRUE;
3359  ind2fv[nfv]=k;
3360  nfv++;
3361  }
3362  else
3363  fv[k]=FALSE;
3364  }
3365  else
3366  fv[k]=FALSE;
3367  }
3368 
3369  if (fname==NULL)
3370  {
3371  f_out_box=NULL;
3372  f_out_point=NULL;
3373  }
3374  else
3375  {
3376  /* Check if we can create the output files */
3377  CreateFileName(NULL,fname,"_samples",SOL_EXT,&fsols_box);
3378  f_out_box=fopen(GetFileFullName(&fsols_box),"w");
3379  if (!f_out_box)
3380  Error("Could not open box sample output file");
3381 
3382  CreateFileName(NULL,fname,NULL,LINKS_EXT,&fsols_point);
3383  f_out_point=fopen(GetFileFullName(&fsols_point),"w");
3384  if (!f_out_point)
3385  Error("Could not open box sample output file");
3386  }
3387 
3388  if (sb!=NULL)
3389  InitListOfBoxes(sb);
3390 
3391  nv=GetCSNumVariables(cs);
3392  ne=GetCSNumEquations(cs);
3393 
3394  if (ndof==NO_UINT)
3395  {
3396  /* try to get the number of dof from the system (vars-equations) */
3397  if (ne>=nv)
3398  Error("Over/Well-constrained system. Please indicate the number of dof in the call");
3399  ndof=nv-ne;
3400  }
3401  #if (_DEBUG>1)
3402  printf("Initial reduction (s:%g)\n",GetBoxSumSide(NULL,init_box));
3403  #endif
3404  if (MaxReduction(p,~DUMMY_VAR,&reduction,init_box,cs)==EMPTY_BOX)
3405  end=TRUE;
3406  else
3407  end=FALSE;
3408 
3409  #if (_DEBUG>1)
3410  if (!end)
3411  {
3412  printf("[CS] (s:%g)",GetBoxSumSide(NULL,init_box));
3413  PrintBox(stdout,init_box);
3414  }
3415  else
3416  printf("Inconsistent system while sampling\n");
3417  fflush(stdout);
3418  #endif
3419 
3420  NEW(attempts,ndof,unsigned int);
3421  NEW(bl,ndof,Tbox);
3422  maxAttemptsPerLevel=10;
3423 
3424  ns=0; /*samples already determined*/
3425  nt=0; /*time we tried to sample so far*/
3426  while((!end)&&(ns<nsamples))
3427  {
3428  ok=TRUE;
3429 
3430  CopyBox(&b,init_box);
3431 
3432  /*fix ndof variables*/
3433  level=0;
3434  for(k=0;k<ndof;k++)
3435  attempts[k]=0;
3436 
3437  while((level<ndof)&&(!end))
3438  {
3439  /*Keep a copy of the box BEFORE fixing the new variable at the current
3440  'level'. This is used when backtracking to recover the state before this
3441  assigment*/
3442  CopyBox(&(bl[level]),&b);
3443 
3444  do {
3445  /*select one of the still not fixed variables*/
3446  d=ind2fv[randomMax(nfv-1)];
3447  r=GetBoxInterval(d,&b);
3448  } while (IntervalSize(r)<=smallSigma);
3449 
3450  #if (_DEBUG>1)
3451  printf("[CS](level %u/%u bs:%f)",level,ndof,GetBoxSumSide(NULL,&b));
3452  #endif
3453 
3454  {
3455  Tinterval raux;
3456  double c,l;
3457 
3458  c=IntervalCenter(r);
3459  l=IntervalSize(r)/2;
3460 
3461  NewInterval(c-l,c+l,&raux);
3462 
3463  /*Now change the current box ,b*/
3464  v=randomInInterval(&raux);
3465  }
3466  //v=randomInInterval(r);
3467 
3468  NewInterval(v,v,&newr);
3469 
3470  SetBoxInterval(d,&newr,&b);
3471 
3472  /* Change the variable ranges to those in b */
3473  UnUpdateCuikSystem(cs);
3474  VariablesFromBox(&b,&(cs->orig_variables));
3475 
3476  attempts[level]++;
3477 
3478  #if (_DEBUG>1)
3479  printf("(attempts %u/%u)->fixing %u to %f \n",
3480  attempts[level],maxAttemptsPerLevel,d,v);
3481  #endif
3482 
3483  /* And reduce the systems as much as possible */
3484  ok=((UpdateCuikSystem(p,cs))&&
3485  (MaxReduction(p,~DUMMY_VAR,&reduction,&b,cs)!=EMPTY_BOX));
3486 
3487  if (ok)
3488  {
3489  if (newtonIterations>0)
3490  {
3491  if ((CuikNewtonInBox(p,&b,sol,&b_sol,cs)&(CONVERGED_IN_GLOBAL|CONVERGED_IN_BOX))>0)
3492  {
3493  fprintf(f_out_box,"Newton (%g)",ErrorInSolution(&b_sol,cs));
3494  PrintBoxSubset(f_out_box,cs->orig_notDummyVar,cs->orig_varNames,&b_sol);
3495  fflush(f_out_box);
3496  }
3497  DeleteBox(&b_sol);
3498  }
3499  level++;
3500 
3501  #if (_DEBUG>1)
3502  printf("[CS] (l:%u s:%g)",level,GetBoxSumSide(NULL,&b));
3503  PrintBox(stdout,&b);
3504  #endif
3505  }
3506  else
3507  {
3508  #if (_DEBUG>1)
3509  printf("Inconsistent system while sampling. Backtracking\n");
3510  #endif
3511 
3512  /*Undo the last assigment*/
3513  DeleteBox(&b);
3514  CopyBox(&b,&(bl[level]));
3515  DeleteBox(&(bl[level]));
3516 
3517  if (attempts[level]>maxAttemptsPerLevel)
3518  {
3519  attempts[level]=0;
3520  if (level>0)
3521  {
3522  level--;
3523  /*move to the state just before the assigment at leve-1*/
3524  DeleteBox(&b);
3525  CopyBox(&b,&(bl[level]));
3526  DeleteBox(&(bl[level]));
3527  }
3528  }
3529  }
3530  }
3531 
3532  if (ok)
3533  {
3534  /* Last degree of freedom is not fixed but we solve the cuiksystem in the box */
3535  InitListOfBoxes(&solutions);
3536 
3537  /*See if there are solutions for the fixed ranges*/
3538  ChangeParameter(CT_N_SOLUTIONS,nsamples-ns,p);
3539  SolveCuikSystem(p,FALSE,NULL,&b,f_out_box,&solutions,cs);
3540 
3541  /*We have to print the samples*/
3542  GetCSSystemVars(&systemVars,cs);
3543  InitIterator(&it,&solutions);
3544  First(&it);
3545  while((!EndOfList(&it))&&(ns<nsamples))
3546  {
3547  bAux=(Tbox *)GetCurrent(&it);
3548 
3549  if (f_out_point!=NULL)
3550  {
3551  /* Print the center of the box into the point file */
3552  /* We only print values for the system vars */
3553  for(i=0;i<nv;i++)
3554  {
3555  if (systemVars[i])
3556  fprintf(f_out_point," %.12g",IntervalCenter(GetBoxInterval(i,bAux)));
3557  }
3558  fprintf(f_out_point,"\n");
3559  }
3560  if (sb!=NULL)
3561  {
3562  NEW(box,1,Tbox);
3563 
3564  CopyBox(box,bAux);
3565 
3566  AddLastElement((void *)box,sb);
3567  }
3568 
3569  ns++;
3570  Advance(&it);
3571  }
3572  free(systemVars);
3573 
3574  fflush(f_out_point);
3575  fflush(f_out_box);
3576 
3577  /*Remove all boxes from the list and the current box*/
3578  DeleteListOfBoxes(&solutions);
3579  }
3580 
3581  DeleteBox(&b);
3582 
3583  nt++;
3584  if ((ntries!=NO_UINT)&&(nt==ntries))
3585  end=TRUE;
3586 
3587  }
3588 
3589  if (f_out_box!=NULL)
3590  {
3591  DeleteFileName(&fsols_box);
3592  fclose(f_out_box);
3593  }
3594  if (f_out_point!=NULL)
3595  {
3596  fclose(f_out_point);
3597  DeleteFileName(&fsols_point);
3598  }
3599 
3600  /*Restore the user given small_sigma and number of solutions*/
3603 
3604  free(attempts);
3605  free(bl);
3606 
3607  free(fv);
3608  free(ind2fv);
3609  free(sol);
3610 
3611  UnUpdateCuikSystem(cs);
3612  VariablesFromBox(&orig_ranges,&(cs->orig_variables));
3613  DeleteBox(&orig_ranges);
3614 
3615  return(!end);
3616 }
3617 
3618 unsigned int CuikNewtonSimp(Tparameters *p,double *x,TCuikSystem *cs)
3619 {
3620  boolean converged=FALSE;
3621  unsigned int out=DIVERGED;
3622 
3623  if (UpdateCuikSystem(p,cs))
3624  {
3625  if (cs->simp_nequations==0)
3626  {
3627  out=CONVERGED_IN_BOX;
3628  }
3629  else
3630  {
3631  TNewton newton;
3632  double *Jx_d;
3633  double *b_d;
3634 
3635  double epsilon,nullSingularValue;
3636  double errorVal;
3637  int err;
3638  unsigned int nStep,nStepMax;
3639 
3640  #if (_DEBUG>2)
3641  {
3642  unsigned int i;
3643 
3644  printf("Starting Newton Iteration form: [");
3645  for(i=0;i<cs->simp_nvariables;i++)
3646  printf("%f ",x[i]);
3647  printf("]\n");
3648  }
3649  #endif
3650  InitNewton(cs->simp_nee,cs->simp_nvariables,&newton);
3651  Jx_d=GetNewtonMatrixBuffer(&newton);
3652  b_d=GetNewtonRHBuffer(&newton);
3653 
3654  epsilon=GetParameter(CT_EPSILON,p);
3655  nullSingularValue=epsilon/100;
3656 
3657  nStepMax=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p);
3658  if (nStepMax==0)
3659  Error("Parameter MAX_NEWTON_ITERATIONS must be larger than 0 to use CuikNewton");
3660 
3661  nStep=0;
3662 
3663  while((!converged)&&(nStep<nStepMax))
3664  {
3665  EvaluateJacobianInVector(x,cs->simp_nee,cs->simp_nvariables,Jx_d,&(cs->J));
3667 
3668  err=NewtonStep(nullSingularValue,x,&errorVal,&newton);
3669 
3670  if (err)
3671  nStep=nStepMax;
3672  else
3673  {
3674  #if (_DEBUG>2)
3675  {
3676  unsigned int i;
3677 
3678  printf(" Iteration: %u error: %g",nStep,errorVal);
3679  #if (_DEBUG>3)
3680  printf(" x: [\n");
3681  for(i=0;i<cs->simp_nvariables;i++)
3682  printf("%f ",x[i]);
3683  printf("]");
3684  #endif
3685  printf("\n");
3686  }
3687  #endif
3688 
3689  /* stopCriterion test */
3690  if(errorVal<epsilon)
3691  converged=TRUE;
3692 
3693  nStep++;
3694  }
3695  }
3696 
3697  if (cs->simp_tp!=NULL)
3698  ArrayPi2Pi(cs->simp_nvariables,cs->simp_tp,x);
3699 
3700  DeleteNewton(&newton);
3701 
3702  if ((converged)&&(ErrorInSimpCSEquations(p,x,cs)<epsilon))
3703  out=CONVERGED_IN_GLOBAL;
3704  else
3705  out=DIVERGED;
3706  }
3707  }
3708  else
3709  Error("Inconsistent input cuiksystem");
3710 
3711  return(out);
3712 }
3713 
3714 unsigned int CuikNewtonInBox(Tparameters *p,Tbox *bIn,double *sol,Tbox *b_sol,TCuikSystem *cs)
3715 {
3716  boolean converged=FALSE;
3717  unsigned int out=DIVERGED;
3718 
3719  if (UpdateCuikSystem(p,cs))
3720  {
3721  if (cs->simp_nequations==0)
3722  {
3723  unsigned int i;
3724 
3725  /* The system of equations is empty -> just pic a random value for the variables */
3726  for(i=0;i<cs->orig_nvariables;i++)
3727  sol[i]=randomInInterval(GetBoxInterval(i,bIn));
3728  InitBoxFromPoint(cs->orig_nvariables,sol,b_sol);
3729  out=CONVERGED_IN_BOX;
3730  }
3731  else
3732  {
3733  Tbox bsimp;
3734  Tinterval c,*r;
3735 
3736  unsigned int nv,ne,bs;
3737  unsigned int i,j,k,l;
3738 
3739  double *m,*h;
3740  double *x;
3741  double *Jx_d;
3742  double *b_d;
3743 
3744  /* Newton required variables */
3745  TNewton newton;
3746 
3747  double epsilon;
3748  double nullSingularValue;
3749  double errorVal;
3750  unsigned int nStep,nStepMax;
3751  int err;
3752  Tbox box;
3753 
3754  bs=GetBoxNIntervals(bIn);
3755  if (cs->orig_nvariables<bs)
3756  Error("Box size missmatch in CuikNewtonInBox");
3757  else
3758  {
3759  if (cs->orig_nvariables>bs)
3760  {
3761  if (cs->orig_nvariables==(bs+GetNumDummyVariables(&(cs->orig_variables))))
3762  {
3763  /* We are given a solution box without the dummy vars */
3764  /* We need to compute the values for the dummy vars from the system ones*/
3765 
3766  GenerateInitialBox(&box,cs); /*all variables to initial ranges*/
3767 
3768  SetBoxSubset(cs->orig_systemVar,bIn,&box); /* only dummies to initial ranges */
3769  RegenerateSolution(p,&box,cs); /* define dummies from system variables */
3770  }
3771  else
3772  Error("Box size missmatch in CuikNewtonInBox");
3773  }
3774  else
3775  CopyBox(&box,bIn);
3776  }
3777 
3778  nStepMax=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,p);
3779  if (nStepMax==0)
3780  Error("Parameter MAX_NEWTON_ITERATIONS must be larger than 0 to use CuikNewton");
3781 
3782  SimpleFromOriginal(&box,&bsimp,cs->orig2s);
3783 
3784  /* We will add some variables and equations to deal with ranges */
3785  #if (NEWTON_WITHIN_RANGES)
3786  nv=cs->simp_nvariables+cs->simp_nvariables;
3787  ne=cs->simp_nee+cs->simp_nvariables;
3788  #else
3789  nv=cs->simp_nvariables;
3790  ne=cs->simp_nee;
3791  #endif
3792 
3793  /* Space for the variable ranges */
3794  NEW(m,cs->simp_nvariables,double);
3795  NEW(h,cs->simp_nvariables,double);
3796  for(i=0;i<cs->simp_nvariables;i++)
3797  {
3798  r=GetBoxInterval(i,&bsimp);
3799  m[i]=IntervalCenter(r);
3800  h[i]=IntervalSize(r)/2.0;
3801  }
3802 
3803  /* Matrices and arrays used in the Newton iteration */
3804  NEW(x,nv,double);
3805  for(i=0;i<cs->simp_nvariables;i++)
3806  x[i]=randomInInterval(GetBoxInterval(i,&bsimp));
3807 
3808  for(i=cs->simp_nvariables,j=0;i<nv;i++,j++)
3809  x[i]=asin((x[j]-m[j])/h[j]);
3810 
3811  #if (_DEBUG>2)
3812  {
3813  printf("Starting Newton Iteration form: x=[");
3814  for(i=0;i<nv;i++)
3815  printf("%f ",x[i]);
3816  printf("]\n");
3817  }
3818  #endif
3819 
3820  InitNewton(ne,nv,&newton);
3821  Jx_d=GetNewtonMatrixBuffer(&newton);
3822 
3823  k=ne*nv;
3824  if (k!=(cs->simp_nee*cs->simp_nvariables))
3825  {
3826  /* If we have limit constraints just init the full
3827  buffer to zero. */
3828  for(i=0;i<k;i++)
3829  Jx_d[i]=0;
3830  }
3831 
3832  b_d=GetNewtonRHBuffer(&newton);
3833 
3834  epsilon=GetParameter(CT_EPSILON,p);
3835  nullSingularValue=epsilon/100;
3836 
3837  nStep=0;
3838 
3839  while((!converged)&&(nStep<nStepMax))
3840  {
3841  EvaluateJacobianInVector(x,ne,nv,Jx_d,&(cs->J));
3843 
3844  for(i=cs->simp_nvariables,j=0,l=cs->simp_nee;i<nv;i++,j++,l++)
3845  {
3846  /* 'j' is the index for the original variable 'v' */
3847  /* 'i' is the index for the new variable 'q' */
3848  NewtonSetMatrix(l,j,1,&newton);
3849  NewtonSetMatrix(l,i,-h[j]*cos(x[i]),&newton);
3850 
3851  NewtonSetRH(l,(x[j]-m[j]-h[j]*sin(x[i])),&newton);
3852  }
3853 
3854  errorVal=Norm(ne,b_d);
3855 
3856  //fprintf(stderr,"%u Newton Error: %g\n",nStep,errorVal);
3857 
3858  converged=(errorVal<epsilon);
3859 
3860  if (!converged)
3861  {
3862  err=NewtonStep(nullSingularValue,x,&errorVal,&newton);
3863 
3864  if (err)
3865  nStep=nStepMax;
3866  else
3867  {
3868  #if (_DEBUG>2)
3869  printf(" Iteration: %u error: %g",nStep,errorVal);
3870  #if (_DEBUG>3)
3871  printf(" x: [\n");
3872  for(i=0;i<cs->simp_nvariables;i++)
3873  printf("%f ",x[i]);
3874  printf("]");
3875  #endif
3876  printf("\n");
3877  #endif
3878 
3879  nStep++;
3880  }
3881  }
3882  }
3883  DeleteNewton(&newton);
3884 
3885  if (cs->simp_tp!=NULL)
3886  ArrayPi2Pi(cs->simp_nvariables,cs->simp_tp,x);
3887 
3888  for(i=0;i<cs->simp_nvariables;i++)
3889  {
3890  NewInterval(x[i],x[i],&c);
3891  SetBoxInterval(i,&c,&bsimp);
3892  }
3893 
3894  CopyBox(b_sol,&box);
3895  UpdateOriginalFromSimple(&bsimp,b_sol,cs->orig2s);
3896 
3897  /* Some dummy variables in original system might not be present in
3898  the simplified system but their value can be trivially deduced
3899  from the system variables*/
3900  RegenerateSolution(p,b_sol,cs);
3901 
3902  /*At this point b_sol must be a punctual box (fully defined) */
3903  for(i=0;i<cs->orig_nvariables;i++)
3904  sol[i]=IntervalCenter(GetBoxInterval(i,b_sol));
3905 
3906  if (!converged) //((!converged)||(ErrorInSolution(b_sol,cs)>epsilon))
3907  out=DIVERGED;
3908  else
3909  {
3910  Tbox init_box;
3911 
3912  GenerateInitialBox(&init_box,cs);
3913 
3914  if ((ErrorInInequalities(b_sol,cs)>epsilon)||
3915  (!PointInBox(cs->orig_notDummyVar,cs->orig_nvariables,sol,epsilon,&init_box)))
3917  else
3918  {
3919  if (PointInBox(cs->orig_systemVar,cs->orig_nvariables,sol,epsilon,&box))
3920  out=CONVERGED_IN_BOX;
3921  else
3922  out=CONVERGED_IN_GLOBAL;
3923  }
3924 
3925  DeleteBox(&init_box);
3926  }
3927 
3928  DeleteBox(&bsimp);
3929  free(x);
3930  free(m);
3931  free(h);
3932  DeleteBox(&box);
3933  }
3934  }
3935  else
3936  Error("Inconsistent input cuiksystem");
3937 
3938  return(out);
3939 }
3940 
3941 /*
3942  Find a solution of a cuiksystem set of equations
3943  using the Newton-Rhapson method. If the system is undetermined,
3944  the method is based on the Moor-Penrose generalised inverse.
3945  The method can diverge if the initial point is far from the solutions of the system.
3946  */
3947 boolean CuikNewton(Tparameters *p,double *sol,Tbox *b_sol,TCuikSystem *cs)
3948 {
3949  Tbox init_box;
3950  boolean converged;
3951 
3952  GenerateInitialBox(&init_box,cs);
3953 
3954  converged=((CuikNewtonInBox(p,&init_box,sol,b_sol,cs)&(CONVERGED_IN_BOX|CONVERGED_IN_GLOBAL))>0);
3955 
3956  DeleteBox(&init_box);
3957 
3958  return(converged);
3959 }
3960 
3962  Tbox *bIn,double *sol,Tbox *b_sol,TCuikSystem *cs)
3963 {
3964  boolean converged=FALSE;
3965  unsigned int out=DIVERGED;
3966 
3967  if (UpdateCuikSystem(p,cs))
3968  {
3969  if (cs->simp_nequations==0)
3970  {
3971  unsigned int i;
3972 
3973  /* The system of equations is empty -> just pic a random value for the variables */
3974  for(i=0;i<cs->orig_nvariables;i++)
3975  sol[i]=randomInInterval(GetBoxInterval(i,bIn));
3976  InitBoxFromPoint(cs->orig_nvariables,sol,b_sol);
3977  out=CONVERGED_IN_BOX;
3978  }
3979  else
3980  {
3981  Tbox box,bsimp;
3982  double *x,*nx,*f,*J,*g;
3983  double alpha,c,t,tau;
3984  unsigned int bs,i,k,nSteps,ne;
3985  double error,e,epsilon,d;
3986  boolean done,stalled;
3987  Tinterval range,*is;
3988  unsigned int bounds;
3989 
3990  bounds=1; /* 0: do not consider 1: weigth 2:crop */
3991 
3992  bs=GetBoxNIntervals(bIn);
3993  if (cs->orig_nvariables<bs)
3994  Error("Box size missmatch in CuikGradientInBox");
3995  else
3996  {
3997  if (cs->orig_nvariables>bs)
3998  {
3999  if (cs->orig_nvariables==(bs+GetNumDummyVariables(&(cs->orig_variables))))
4000  {
4001  /* We are given a solution box without the dummy vars */
4002  /* We need to compute the values for the dummy vars from the system ones*/
4003 
4004  GenerateInitialBox(&box,cs); /*all variables to initial ranges*/
4005 
4006  SetBoxSubset(cs->orig_systemVar,bIn,&box); /* only dummies to initial ranges */
4007  RegenerateSolution(p,&box,cs); /* define dummies from system variables */
4008  }
4009  else
4010  Error("Box size missmatch in CuikGradientInBox");
4011  }
4012  else
4013  CopyBox(&box,bIn);
4014  }
4015 
4016  SimpleFromOriginal(&box,&bsimp,cs->orig2s);
4017  is=GetBoxIntervals(&bsimp);
4018 
4019  epsilon=GetParameter(CT_EPSILON,p);
4020 
4021  /* initial point */
4022  NEW(x,cs->simp_nvariables,double);
4023  for(i=0;i<cs->simp_nvariables;i++)
4024  x[i]=randomInInterval(&(is[i]));
4025 
4026  /* Space to evaluate the equations */
4027  if (bounds==1)
4028  ne=cs->simp_nee+cs->simp_nvariables;
4029  else
4030  ne=cs->simp_nee;
4031 
4032  NEW(nx,cs->simp_nvariables,double); /* new x */
4033  NEW(f,ne,double); /* evaluation of equations */
4034  NEW(g,cs->simp_nvariables,double); /* gradient at x */
4035  NEWZ(J,ne*cs->simp_nvariables,double); /* Jacobian of the equations (initialized to 0) */
4036 
4037  nSteps=1;
4038  converged=FALSE;
4039  stalled=FALSE;
4040  while((!converged)&&(!stalled))
4041  {
4042  EvaluateJacobianInVector(x,ne,cs->simp_nvariables,J,&(cs->J));
4044  /* only enter the loop if bounds==1 */
4045  for(k=cs->simp_nee,i=0;k<ne;k++,i++)
4046  {
4047  d=DistanceToInterval(x[i],&(is[i]));
4048  f[k]=d*d;
4049  J[RC2INDEX(k,i,ne,cs->simp_nvariables)]=2*d;
4050  }
4051 
4052  error=Norm(ne,f);
4053  if (nSteps%1000==1)
4054  fprintf(stderr," Error %u: %g\n",nSteps,error);
4055  converged=(error<epsilon/10);
4056  if (!converged)
4057  {
4058  /* obtain the gradient of f1^2+...+f_nv^2 */
4059  TMatrixVectorProduct(ne,cs->simp_nvariables,J,f,g);
4060  e=Norm(cs->simp_nvariables,g);
4061  if (e<epsilon/100)
4062  {
4063  fprintf(stderr," Gradient norm: %g\n",e);
4064  stalled=TRUE;
4065  }
4066  else
4067  {
4068  /* Adjust alpha
4069  Apply backtracking line search with c=tau=0.5 and with p=-gradient
4070  http://en.wikipedia.org/wiki/Backtracking_line_search
4071  */
4072  done=FALSE;
4073  alpha=0.1; /* initial guess */
4074  c=tau=0.5; /* set c,tau parameters */
4075  t=-c*Norm(cs->simp_nvariables,g); /* t=-c*m, m=p^t*g=-g^t*g (with p=-g) */
4076  while((!done)&&(!stalled))
4077  {
4078  /* nx = x + alpha*p = x -alpha*g (cropped to the box if required) */
4079  SumVectorScale(cs->simp_nvariables,x,-alpha,g,nx);
4080  if (bounds==2)
4081  Crop2Box(NULL,cs->simp_nvariables,nx,&bsimp);
4082 
4083  /* evaluate f(nx) */
4085  /* only enter the loop if bounds==1 */
4086  for(k=cs->simp_nee,i=0;k<ne;k++,i++)
4087  {
4088  d=DistanceToInterval(nx[i],&(is[i]));
4089  f[k]=d*d;
4090  }
4091  e=Norm(ne,f);
4092 
4093  /* Test if the decrease in error is enough using Armijo-Goldstein condition */
4094  if ((error-e)<alpha*t)
4095  {
4096  alpha*=tau;
4097  stalled=(alpha<epsilon);
4098  }
4099  else
4100  done=TRUE;
4101  }
4102  if (!stalled)
4103  memcpy(x,nx,cs->simp_nvariables*sizeof(double)); /* x<-nx */
4104  }
4105  }
4106  nSteps++;
4107  }
4108 
4109  if (cs->simp_tp!=NULL)
4110  ArrayPi2Pi(cs->simp_nvariables,cs->simp_tp,x);
4111 
4112  for(i=0;i<cs->simp_nvariables;i++)
4113  {
4114  NewInterval(x[i],x[i],&range);
4115  SetBoxInterval(i,&range,&bsimp);
4116  }
4117 
4118  CopyBox(b_sol,&box);
4119  UpdateOriginalFromSimple(&bsimp,b_sol,cs->orig2s);
4120 
4121  /* Some dummy variables in original system might not be present in
4122  the simplified system but their value can be trivially deduced
4123  from the system variables*/
4124  RegenerateSolution(p,b_sol,cs);
4125 
4126  /*At this point b_sol must be a punctual box (fully defined) */
4127  for(i=0;i<cs->orig_nvariables;i++)
4128  sol[i]=IntervalCenter(GetBoxInterval(i,b_sol));
4129 
4130  if (!converged) //((!converged)||(ErrorInSolution(b_sol,cs)>epsilon))
4131  out=DIVERGED;
4132  else
4133  {
4134  Tbox init_box;
4135 
4136  GenerateInitialBox(&init_box,cs);
4137 
4138  if ((ErrorInInequalities(b_sol,cs)>epsilon)||
4139  (!PointInBox(cs->orig_notDummyVar,cs->orig_nvariables,sol,epsilon,&init_box)))
4141  else
4142  {
4143  if (PointInBox(cs->orig_systemVar,cs->orig_nvariables,sol,epsilon,&box))
4144  out=CONVERGED_IN_BOX;
4145  else
4146  out=CONVERGED_IN_GLOBAL;
4147  }
4148 
4149  DeleteBox(&init_box);
4150  }
4151 
4152  free(x);
4153  free(f);
4154  free(g);
4155  free(J);
4156  DeleteBox(&box);
4157  DeleteBox(&bsimp);
4158 
4159  }
4160  }
4161  else
4162  Error("Inconsistent input cuiksystem");
4163 
4164  return(out);
4165 }
4166 
4167 /*
4168  Find a solution of a cuiksystem set of equations
4169  using a gradient descent method.
4170  */
4171 boolean CuikGradient(Tparameters *p,double *sol,Tbox *b_sol,TCuikSystem *cs)
4172 {
4173  Tbox init_box;
4174  boolean converged;
4175 
4176  GenerateInitialBox(&init_box,cs);
4177 
4178  converged=((CuikGradientInBox(p,&init_box,sol,b_sol,cs)&(CONVERGED_IN_BOX|CONVERGED_IN_GLOBAL))>0);
4179 
4180  DeleteBox(&init_box);
4181 
4182  return(converged);
4183 }
4184 
4185 /*
4186  Takes a cuik systema and returns all solutions.
4187  Solutions are stored in file 'f_out' (if defined) and in list 'sol'
4188  (if defined), or both.
4189 
4190  This procedure is used for single-cpu versions of Cuik.
4191  */
4193  boolean restart,char *fstate,Tbox *searchSpace,
4194  FILE *f_out,Tlist *sol,TCuikSystem *cs)
4195 {
4196  Theap boxes;
4197  #if (_DEBUG>1)
4198  unsigned int nbox=0;
4199  #endif
4200 
4201  Tbox b;
4202  unsigned int c; /* output of ReduceBox */
4203  unsigned int current_level; /* level of the current box in the search three */
4204  Tbox init_box;
4205  boolean done;
4206  unsigned int nb; /*boxes for recovery mode*/
4207  unsigned int statePeriod;
4208  unsigned int nsols;
4209 
4210  if (!cs->scalar)
4211  Error("SolveCuikSystem only operates on scalar systems");
4212 
4213  /************************************************************************************/
4214  /************************************************************************************/
4215  /************************************************************************************/
4216 
4217  if (UpdateCuikSystem(p,cs))
4218  {
4219  if (cs->simp_empty)
4220  {
4221  Tbox b;
4222 
4223  /* The system of equations is empty -> just pic a random value for the variables */
4224  InitBox(cs->simp_nvariables,NULL,&b);
4225  PostProcessBox(p,REDUCED_BOX_WITH_SOLUTION,f_out,sol,&boxes,&b,cs);
4226  DeleteBox(&b);
4227  }
4228  else
4229  {
4230  switch(cs->searchMode)
4231  {
4232  case DEPTH_FIRST_SEARCH:
4233  InitHeapOfBoxes(CmpBoxDepthFirst,NULL,&boxes);
4234  break;
4235  case BREADTH_FIRST_SEARCH:
4236  InitHeapOfBoxes(CmpBoxBreadthFirst,NULL,&boxes);
4237  break;
4238  case MINIMIZATION_SEARCH:
4239  InitHeapOfBoxes(CmpBoxesEquation,(void *)cs,&boxes);
4240  break;
4241  }
4242 
4243  if ((restart)&&(fstate!=NULL))
4244  {
4245  Tlist pboxes;
4246 
4247  LoadCSState(fstate,&pboxes,cs);
4248  AddList2Heap(&pboxes,&boxes);
4249  DeleteListOfBoxes(&pboxes);
4250  }
4251  else
4252  {
4253  if (searchSpace==NULL)
4254  {
4255  BoxFromVariables(&init_box,&(cs->variables));
4256  AddBox2HeapOfBoxes(&init_box,&boxes);
4257  DeleteBox(&init_box);
4258  }
4259  else
4260  {
4261  SimpleFromOriginal(searchSpace,&init_box,cs->orig2sd);
4262  AddBox2HeapOfBoxes(&init_box,&boxes);
4263  }
4264 
4265  InitStatistics(1,HeapOfBoxesVolume(cs->systemVar,&boxes),&(cs->st));
4266  }
4267 
4268  current_level=0;
4269  nb=0;
4270  statePeriod=(unsigned int)GetParameter(CT_STATE_PERIOD,p);
4271  nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p);
4272 
4273  done=FALSE;
4274 
4275  /*the cuik solve process itself*/
4276  do {
4277  if(!HeapEmpty(&boxes))
4278  {
4279  /*Get a new box*/
4280 
4281  if ((statePeriod>0)&&(fstate!=NULL))
4282  {
4283  nb++;
4284  if (nb==statePeriod)
4285  {
4286  Tlist pboxes;
4287 
4288  Heap2List(&pboxes,&boxes);
4289  SaveCSState(fstate,&pboxes,cs);
4290  DeleteListOfBoxes(&pboxes);
4291  nb=0;
4292  }
4293  }
4294 
4295  NewBoxProcessed(&(cs->st));
4296 
4297  /*The box is extracted to avoid another process
4298  to get the same box*/
4299  ExtractMinElement(&b,&boxes);
4300 
4301  current_level=GetBoxLevel(&b);
4302 
4303  NewMaxLevel(current_level,&(cs->st));
4304 
4305  #if (_DEBUG>0)
4306  fprintf(stderr,"<%g %g>[%u]",
4307  GetBoxVolume(cs->systemVar,&b),
4308  GetBoxSize(cs->systemVar,&b),
4309  current_level);
4310  #endif
4311 
4312  #if (_DEBUG>1)
4313  printf("\n\n%u: Analizing box: ",nbox);
4314  nbox++;
4315  PrintBox(stdout,&b);
4316  printf(" Box level : %u\n",GetBoxLevel(&b));
4317  printf(" Box volume : %g\n",GetBoxVolume(cs->systemVar,&b));
4318  printf(" Box size : %g\n",GetBoxSize(cs->systemVar,&b));
4320  printf(" Box penalty : %g\n",EvaluateEqMin((void *)&b,(void *)cs));
4321  #endif
4322 
4323  /* Reduce the box by all but dummy vars */;
4324  c=ReduceBox(p,~DUMMY_VAR,&b,cs);
4325 
4326  #if (_DEBUG>0)
4327  fprintf(stderr," -> ");
4328  #endif
4329 
4330  PostProcessBox(p,c,f_out,sol,&boxes,&b,cs);
4331 
4332  if (nsols>0)
4333  done=(GetNSolutionBoxes(&(cs->st))>=nsols);
4334 
4335  DeleteBox(&b);
4336  }
4337  } while((!done)&&(!HeapEmpty(&boxes))); /*Until everything is completed*/
4338 
4339  DeleteHeap(&boxes); /*for sanity we delete the empty list*/
4340 
4341  PrintStatistics((f_out==NULL?stdout:f_out),&(cs->st));
4342  }
4343  }
4344 }
4345 
4346 
4347 #if (_USE_MPI)
4348 /*
4349  In multi-cpu versions we use a MPI version of CuikSolve
4350  One of the CPUs takes the role of scheduler in charge of managing the
4351  lists of boxes pending to be processed and classifing boxes out of
4352  reduction process as solutions of boxes to be split.
4353  The rest of CPUs take the charge of reducing boxes (i.e., of executing
4354  ReduceBox to the boxes received from the scheduler) and of returning
4355  the resulting boxes (with the associated result code) to the
4356  scheduler.
4357 
4358  The scheduler has to take into account that some child nodes can
4359  'die' while reducing boxes. So it has to keep track of when a box was
4360  sent to a child and prediodically check whether a timeout was been reached.
4361  If so, the corresponding processor is considered as 'dead' the
4362  box sent is recovered and added to the list of boxes to be processed
4363  (i.e., send to other child nodes still alive).
4364 
4365  The scheduler should considere the extreme case where all child process die
4366  and should take care of "awakening" dead processors.
4367  This is not implemented.... till now.
4368 */
4370  boolean restart,char *fstate,Tbox *searchSpace,
4371  FILE *f_out,TCuikSystem *cs)
4372 {
4373  Theap boxes; /*queued boxes*/
4374  Tbox b;
4375  unsigned int c;
4376  unsigned int nr;
4377  unsigned int current_level;
4378 
4379  /*Variables to set up the parallelism*/
4380  unsigned int in_process; /* number of boxes send to child processors and still
4381  in process */
4382  unsigned int available; /* number of child processors available */
4383  signed int np; /* number of processors used (np-1) is the number of childs (process
4384  0 is the scheduler) */
4385  MPI_Status status; /* Output status of a MPI command */
4386  MPI_Request *request; /* Communication request. When the scheduller sends out a box
4387  is starts a communication request */
4388  unsigned int buffer_size; /* Size of a buffer of doubles where we store the
4389  information of a box */
4390  double **buffers_out; /* boxes send to the child processors */
4391  double **buffers_in; /* boxes returned by the child processors */
4392  signed int i,completed; /* MPI_Testany returns completed=1 if any of the pending
4393  communications requests has been replied (then, 'i'
4394  is the number of the compleated request)*/
4395  boolean *lost_packet; /* true if a box was never returned */
4396  time_t *time_stamp; /* time when we send out a box */
4397  time_t deadline; /* deadline (in seconds) used to compute the maximum expected
4398  return time for a box*/
4399  Tbox init_box; /* initial search space */
4400  unsigned int nb;
4401  unsigned int statePeriod;
4402 
4403  unsigned int nsols;
4404  boolean done;
4405 
4406  if (!cs->scalar)
4407  Error("MPI_SolveCuikSystem only operates on scalar systems");
4408 
4409  /*lowest possible priority but not as low as that of the children processors*/
4410  /*setpriority(PRIO_PROCESS,0,PRIO_MAX-1); */
4411 
4412  MPI_Comm_size(MPI_COMM_WORLD,&np); /*total number of processes (take into
4413  account that this routine is process number 0)*/
4414 
4415  if (UpdateCuikSystem(p,cs))
4416  {
4417  switch(cs->searchMode)
4418  {
4419  case DEPTH_FIRST_SEARCH:
4420  InitHeapOfBoxes(CmpBoxDepthFirst,NULL,&boxes);
4421  break;
4422  case BREADTH_FIRST_SEARCH:
4423  InitHeapOfBoxes(CmpBoxBreadthFirst,NULL,&boxes);
4424  break;
4425  case MINIMIZATION_SEARCH:
4426  InitHeapOfBoxes(CmpBoxesEquation,(void *)cs,&boxes);
4427  break;
4428  }
4429 
4430  BoxFromVariables(&init_box,&(cs->variables));
4431 
4432  /* Reserve space for the boxes sent/received and associated information */
4433  /*All boxes are the same size as the initial one*/
4434  buffer_size=GetBoxBufferSize(&init_box);
4435 
4436  if ((restart)&&(fstate!=NULL))
4437  {
4438  Tlist pboxes;
4439 
4440  LoadCSState(fstate,&pboxes,cs);
4441  AddList2Heap(&pboxes,&boxes);
4442  DeleteListOfBoxes(&pboxes);
4443  }
4444  else
4445  {
4446  if (searchSpace==NULL)
4447  AddBox2HeapOfBoxes(&init_box,&boxes);
4448  else
4449  {
4450  Tbox lb;
4451 
4452  SimpleFromOriginal(searchSpace,&lb,cs->orig2sd);
4453  AddBox2HeapOfBoxes(&lb,&boxes);
4454  DeleteBox(&lb);
4455  }
4456 
4457  InitStatistics(np,HeapOfBoxesVolume(cs->systemVar,&boxes),&(cs->st));
4458  }
4459  DeleteBox(&init_box);
4460 
4461  current_level=0;
4462 
4463  NEW(buffers_out,np,double*);
4464  NEW(buffers_in,np,double*);
4465 
4466  NEW(request,np,MPI_Request);
4467  NEW(lost_packet,np,boolean);
4468  NEW(time_stamp,np,time_t);
4469 
4470  for(i=1;i<np;i++)
4471  {
4472  request[i]=MPI_REQUEST_NULL;
4473  NEW(buffers_out[i],buffer_size,double);
4474  NEW(buffers_in[i],buffer_size,double);
4475  lost_packet[i]=FALSE;
4476  }
4477 
4478  request[0]=MPI_REQUEST_NULL; /* Processor 0 is the scheduler, do not use it as a child */
4479  in_process=0;
4480  available=(np-1);
4481 
4482  nb=0;
4483  statePeriod=GetParameter(CT_STATE_PERIOD,p);
4484 
4485  nsols=(unsigned int)GetParameter(CT_N_SOLUTIONS,p);
4486 
4487  done=FALSE;
4488 
4489  /*the cuik solve process itself*/
4490  do {
4491 
4492  if ((!done)&& /*we don't have enough solutions*/
4493  (!HeapEmpty(&boxes))&& /* there is something to be processes */
4494  (available>0)) /* and someone ready to process it */
4495  {
4496  /* Search for a free child (at least one must exists) */
4497  i=1;
4498  while ((i<np)&&(request[i]!=MPI_REQUEST_NULL)) i++;
4499 
4500  if (i==np)
4501  Error("wrong number of available processors");
4502  else
4503  {
4504  if ((statePeriod>0)&&(fstate!=NULL))
4505  {
4506  nb++;
4507  if (nb==statePeriod)
4508  {
4509  Tbox btmp;
4510  unsigned int ctmp,ntmp;
4511  Tlist pboxes;
4512  unsigned int kk;
4513 
4514  Heap2List(&pboxes,&boxes);
4515  for(kk=1;kk<np;kk++)
4516  {
4517  if (request[kk]!=MPI_REQUEST_NULL)
4518  {
4519  InitBox(cs->nvariables,NULL,&btmp);
4520  Buffer2Box(&ctmp,&ntmp,buffers_out[kk],&btmp);
4521  AddFirstElement((void *)&btmp,&pboxes);
4522  }
4523  }
4524  SaveCSState(fstate,&pboxes,cs);
4525  DeleteListOfBoxes(&pboxes);
4526  nb=0;
4527  }
4528  }
4529 
4530  /*Get a new box*/
4531  ExtractMinElement(&b,&boxes);
4532 
4533  /* Transform the box into a buffer of doubles */
4534  Box2Buffer(REDUCED_BOX,0,buffers_out[i],&b);
4535 
4536  /* Send it to the iddle child processors */
4537  /* and start waiting for the reply (i.e., the reduced box) */
4538  if (MPI_Send(buffers_out[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD)==MPI_SUCCESS)
4539  {
4540  /* The box is sent and now we start waiting for it */
4541  if (MPI_Irecv(buffers_in[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD,&(request[i]))==MPI_SUCCESS)
4542  {
4543 
4544  current_level=GetBoxLevel(&b);
4545 
4546  NewBoxProcessed(&(cs->st));
4547  NewMaxLevel(current_level,&(cs->st));
4548 
4549  /* One more box is in process */
4550  in_process++;
4551 
4552  /* One less processor is available */
4553  available--;
4554 
4555  #if (_DEBUG>0)
4556  /* Inform about the box launchig */
4557  fprintf(stderr,"b<v:%g, s:%g, l:%u>-> %u\n",
4558  GetBoxVolume(cs->systemVar,&b),
4559  GetBoxSize(cs->systemVar,&b),
4560  current_level,i);
4561  /*
4562  fprintf(stderr," A:%d P:%d Q:%u\n",
4563  available,in_process,HeapSize(&boxes));
4564  */
4565  #endif
4566 
4567  /* Store the time at which we sent out the box */
4568  time_stamp[i]=time(NULL);
4569  /* and, mark the sent box as not lost */
4570  lost_packet[i]=FALSE;
4571 
4572  #if (_DEBUG>1)
4573  printf("Sending box to processors : %u (iddle -> %u box_in_list-> %u)\n",
4574  i,np-in_process-1,HeapSize(&boxes));
4575  printf(" Box: ");
4576  PrintBox(stdout,&b);
4577  #endif
4578 
4579  DeleteBox(&b);
4580  }
4581  else
4582  {
4583  /*The box will never be back: add it to the list and free the processor */
4584  #if (_DEBUG>0)
4585  fprintf(stderr,"RF-> %u\n",i);
4586  #endif
4587 
4588  AddBox2HeapOfBoxes(&b,&boxes);
4589  request[i]=MPI_REQUEST_NULL;
4590  }
4591  }
4592  else
4593  {
4594  /* We didn't manage to send out the box, just return it to the boxes
4595  to be processes*/
4596  #if (_DEBUG>0)
4597  fprintf(stderr,"SF-> %u\n",i);
4598  #endif
4599 
4600  AddBox2HeapOfBoxes(&b,&boxes);
4601  }
4602  }
4603  }
4604 
4605  /* see if we already got any reply from the slaves :-) */
4606  if ((MPI_Testany(np,request,&i,&completed,&status)==MPI_SUCCESS)&&
4607  (completed))
4608  {
4609  /* if 'completed' 'i' is the request completed */
4610  #if (_DEBUG>1)
4611  printf("Receiving box from processors : %u\n",i);
4612  #endif
4613 
4614  available++; /* either if lost or not, the processor becomes available from now on */
4615  request[i]=MPI_REQUEST_NULL;
4616 
4617  if (!lost_packet[i])
4618  {
4619  /* If so, reconstruct the output box and analyze it */
4620  InitBox(cs->nvariables,NULL,&b);
4621 
4622  Buffer2Box(&c,&nr,buffers_in[i],&b);
4623 
4624  AddNBoxReductions(nr,&(cs->st));
4625 
4626  in_process--; /* lost ones are already discounted when classified as lost
4627  (to be able to finish even if lost ones exits)*/
4628 
4629  #if (_DEBUG>0)
4630  fprintf(stderr," %u->b<v:%g s:%g l:%u>(t=%lu): ",
4631  i,
4632  GetBoxVolume(cs->systemVar,&b),
4633  GetBoxSize(cs->systemVar,&b),
4634  GetBoxLevel(&b),
4635  time(NULL)-time_stamp[i]);
4636  /*
4637  fprintf(stderr," A:%d P:%d Q:%u\n",
4638  available,in_process,HeapSize(&boxes));
4639  */
4640  #endif
4641 
4642  PostProcessBox(p,c,f_out,NULL,&boxes,&b,cs);
4643 
4644  if (nsols>0)
4645  done=(GetNSolutionBoxes(&(cs->st))>=nsols);
4646 
4647  DeleteBox(&b);
4648  }
4649  #if (_DEBUG>0)
4650  else
4651  {
4652  /* We receive a box that was thought to be lost. The only think we
4653  do is to mark the child as available again by setting request[i]=MPI_REQUEST_NULL;
4654  below */
4655  fprintf(stderr," lb[%u](t=%lu > %u)\n",i,
4656  time(NULL)-time_stamp[i],MPI_TREAT_BOX_TIMEOUT(cs));
4657  }
4658  #endif
4659  }
4660 
4661 
4662  /* See if one of the send boxes is lost.
4663  All boxes sent before the deadline are considered lost.
4664  Lost boxes are recovered and added to the list of pending boxes.
4665  The processor to which the box was assigned is discarted for future
4666  jobs.
4667  */
4668  deadline=time(NULL)-(time_t)MPI_TREAT_BOX_TIMEOUT(cs);
4669  for(i=1;i<np;i++)
4670  {
4671  if ((!lost_packet[i])&& /*not already lost*/
4672  (request[i]!=MPI_REQUEST_NULL)&& /*and we are waiting for a reply*/
4673  (time_stamp[i]<deadline)) /*for too long actually*/
4674  {
4675  /* we considere the sub-task as lost, we add the box for further process by
4676  another computer and we mark the current message as lost */
4677 
4678  lost_packet[i]=TRUE; /* mark the packet as lost */
4679 
4680  InitBox(cs->nvariables,NULL,&b); /*Recover it and put it again in the list of
4681  boxes to be processed*/
4682  Buffer2Box(&c,&nr,buffers_out[i],&b); /* Error code (c) and additional information
4683  (nr) are empty (this is a box whose process
4684  was not concluded)*/
4685 
4686  NewLostBox(&(cs->st));
4687  #if (_DEBUG>0)
4688  fprintf(stderr," l[%u] (elapsed %lu)\n",i,time(NULL)-time_stamp[i]);
4689  #endif
4690 
4691  /* a time out tipically means a error in the simplex */
4692  PostProcessBox(p,ERROR_IN_PROCESS,f_out,NULL,&boxes,&b,cs);
4693 
4694  DeleteBox(&b);
4695 
4696  in_process--; /* one less box is in process (Observe that the processors is
4697  not marked as available) */
4698  }
4699  }
4700 
4701  fflush(stderr);
4702 
4703  /* Repeat until we don't have enough solutions and there are still some boxes from
4704  where we can get solutions.
4705  If we already have all the desired solutions but some boxes are in_process, we
4706  wait untill their process finishes (so that all processors are ready to receive
4707  the kill signal)
4708  */
4709  } while(((!done)&&(!HeapEmpty(&boxes)))||(in_process>0));
4710 
4711  /* Send a magic packed to the child so that they kill themselves */
4712 
4713  for(i=1;i<np;i++)
4714  {
4715  if (request[i]!=MPI_REQUEST_NULL)
4716  {
4717  /*we have a pending communication with this processor -> cancel it*/
4718  MPI_Cancel(&(request[i]));
4719  }
4720  else
4721  {
4722  /*nothing pending with this processors, just order it to die*/
4723  buffers_out[i][0]=-1.0;
4724  MPI_Send(buffers_out[i],buffer_size,MPI_DOUBLE,i,20,MPI_COMM_WORLD);
4725  }
4726  }
4727 
4728  free(request);
4729  free(lost_packet);
4730  free(time_stamp);
4731 
4732  DeleteHeap(&boxes);
4733 
4734  if (f_out!=NULL)
4735  {
4736  fprintf(f_out,"\n\nCuik executed in %u (%u) child processors\n",available,np-1);
4737  PrintStatistics(f_out,&(cs->st));
4738  }
4739 
4740  DeleteStatistics(&(cs->st));
4741 
4742  for(i=1;i<np;i++)
4743  {
4744  free(buffers_in[i]);
4745  free(buffers_out[i]);
4746  }
4747 
4748  free(buffers_in);
4749  free(buffers_out);
4750  }
4751 }
4752 
4753 /*
4754  This is the process executed by each child process
4755 */
4757 {
4758  if (!cs->scalar)
4759  Error("MPI_TreatBox only operates on scalar systems");
4760 
4761  if (UpdateCuikSystem(p,cs))
4762  {
4763  boolean end;
4764  unsigned int n;
4765  double *buffer;
4766  unsigned int c,nr;
4767  Tbox b;
4768  MPI_Status status;
4769 
4770  InitBox(cs->nvariables,NULL,&b);
4771  n=GetBoxBufferSize(&b);
4772  NEW(buffer,n,double);
4773 
4774  /* A child can be in execution in computers not only devoted to cuik.
4775  We reduce the priority of the cuik process to allow other processes
4776  (those own by the owners of the machines) to run smoothly.
4777  This way we can enlarge the cluster of procesors to almost all
4778  computers in our Lab.
4779  In the future we have to develop programs to check which computers
4780  are on and to add them into the machine list (i.e., the members of
4781  the cluster)
4782  */
4783  /*setpriority(PRIO_PROCESS,0,PRIO_MAX); */
4784 
4785  end=FALSE; /* While the kill buffer is not received */
4786 
4787  while(!end)
4788  {
4789  /* Get new box from the master */
4790  if (MPI_Recv(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD,&status)==MPI_SUCCESS)
4791  {
4792  /* The first double is used to send control messages between the
4793  scheduler and the slave. If negative, the slave dies*/
4794  if (buffer[0]<0)
4795  end=TRUE;
4796  else
4797  {
4798  /* If not the kill buffer, recover the box out of the buffer */
4799  Buffer2Box(&c,&nr,buffer,&b);
4800 
4801  ResetNBoxReductions(&(cs->st)); /* Let's count the box reductions for this
4802  box shrink only*/
4803 
4804  #if (_DEBUG>1)
4805  printf("Box from main processor:");
4806  PrintBox(stdout,&b);
4807  fflush(stdout);
4808  #endif
4809 
4810  /* And reduce it */
4811  c=ReduceBox(p,~DUMMY_VAR,&b,cs);
4812 
4813  #if (_DEBUG>1)
4814  printf("Box out of ReduceBox (%u):",c);
4815  PrintBox(stdout,&b);
4816  fflush(stdout);
4817  #endif
4818 
4819  /* Then pack the result into another buffer */
4820  Box2Buffer(c,GetNBoxReductions(&(cs->st)),buffer,&b);
4821 
4822  /* and send it back to the master */
4823 
4824  #if (_DEBUG>1)
4825  if (MPI_Send(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD)!=MPI_SUCCESS)
4826  printf("Sending to master failed\n");
4827  #else
4828  MPI_Send(buffer,n,MPI_DOUBLE,0,20,MPI_COMM_WORLD);
4829  #endif
4830 
4831  }
4832  }
4833  #if (_DEBUG>1)
4834  else
4835  printf("Receive from master failed\n");
4836  #endif
4837  }
4838 
4839  DeleteBox(&b);
4840  free(buffer);
4841  }
4842 }
4843 #endif
4844 
4845 /*
4846  Returns a box defined by the ranges for the variables given by the user in the
4847  input file. This is the initial search space.
4848  */
4850 {
4851  BoxFromVariables(box,&(cs->orig_variables));
4852 }
4853 
4855 {
4856  if (!UpdateCuikSystem(p,cs))
4857  Error("Inconsistent system in GenerateSimpInitialBox");
4858 
4859  BoxFromVariables(box,&(cs->simp_variables));
4860 }
4861 
4863 {
4864  boolean ok;
4865 
4866  if (UpdateCuikSystem(p,cs))
4867  {
4868  unsigned int i;
4869  Tbox bInit;
4870  double epsilon,rho;
4871  Tinterval all;
4872 
4873  /* If we set the dummies to range [-INF,INF] they are not
4874  adjusted via crop. */
4875  NewInterval(-INF/2,INF/2,&all);
4876 
4877  epsilon=GetParameter(CT_EPSILON,p);
4878  rho=GetParameter(CT_RHO,p);
4879 
4880  InitBox(cs->orig_nvariables,NULL,&bInit);
4881 
4882  /* System and secondary vars already have value in the input box but
4883  dummies and cartesian variables probably not.
4884  These are set to inf range to avoid any limit
4885  in their value when regenerated (boxes commming from
4886  Newton can have extrange values in dummy variables. */
4887  for(i=0;i<cs->orig_nvariables;i++)
4888  {
4889  if ((IsDummyVariable(i,&(cs->orig_variables)))||
4890  (IsCartesianVariable(i,&(cs->orig_variables))))
4891  SetBoxInterval(i,&all,b);
4892  }
4893  DeleteBox(&bInit);
4894 
4895  ok=TRUE;
4896 
4897  /* First we define the value of the dummy variables from the
4898  system ones. They are related by dymmy equations and, given
4899  the system varibles, the dummy variables can be easily defined
4900  via crop. */
4901  for(i=0;((ok)&&(i<cs->orig_nequations));i++)
4902  {
4903  if (IsDummyEquation(i,&(cs->orig_equations)))
4904  ok=(CropEquation(i,DUMMY_VAR,epsilon,rho,b,&(cs->orig_variables),&(cs->orig_equations))!=EMPTY_BOX);
4905  }
4906 
4907  /*
4908  Now we try to define the cartesian variables from the system
4909  and dummy ones.
4910  The separating plane cartesian variables can not be properly bounded
4911  this way but the ones for body vertexes can (and they are the relevant
4912  ones)
4913  */
4914  for(i=0;((ok)&&(i<cs->orig_nequations));i++)
4915  {
4916  if (IsCoordEquation(i,&(cs->orig_equations)))
4917  ok=(CropEquation(i,CARTESIAN_VAR,epsilon,rho,b,&(cs->orig_variables),&(cs->orig_equations))!=EMPTY_BOX);
4918  }
4919  }
4920  else
4921  ok=FALSE;
4922 
4923  return(ok);
4924 }
4925 
4926 unsigned int RegenerateSolutionPoint(Tparameters *p,double *pt,double **rp,TCuikSystem *cs)
4927 {
4928  unsigned int i,k;
4929  Tbox b;
4930 
4931  if (!UpdateCuikSystem(p,cs))
4932  Error("Inconsistent system in RegenerateSolutionPoint");
4933 
4934  NEW(*rp,cs->orig_nvariables,double);
4935 
4936  k=0;
4937  for(i=0;i<cs->orig_nvariables;i++)
4938  {
4939  /*The input box only has values for the input variables*/
4940  if (cs->orig_systemVar[i])
4941  {
4942  (*rp)[i]=pt[k];
4943  k++;
4944  }
4945  else
4946  (*rp)[i]=0.0; /*Non system variables are set to 0. This value is not used */
4947  }
4948 
4949  InitBoxFromPoint(cs->orig_nvariables,*rp,&b);
4950 
4951  if (!RegenerateSolution(p,&b,cs))
4952  Error("Invalid solution point in RegenerateSolutionPoint");
4953 
4954  k=0;
4955  for(i=0;i<cs->orig_nvariables;i++)
4956  {
4957  /*The input box only has values for the input variables (system and secondary)*/
4958  if (!cs->orig_systemVar[i])
4959  (*rp)[i]=IntervalCenter(GetBoxInterval(i,&b));
4960  }
4961  DeleteBox(&b);
4962 
4963  return(cs->orig_nvariables);
4964 }
4965 
4966 
4968 {
4969  if (UpdateCuikSystem(p,cs))
4970  {
4971  BoxFromVariables(boxO,&(cs->orig_variables));
4972  UpdateOriginalFromSimple(boxS,boxO,cs->orig2s);
4973  }
4974  else
4975  Error("Inconsistent input cuiksystem");
4976 }
4977 
4978 unsigned int RegenerateOriginalPoint(Tparameters *p,double *s,double **o,
4979  TCuikSystem *cs)
4980 {
4981  if (UpdateCuikSystem(p,cs))
4982  {
4985  }
4986  else
4987  Error("Inconsistent input cuiksystem");
4988 
4989  return(cs->orig_nvariables);
4990 }
4991 
4992 unsigned int GenerateSimplifiedPoint(Tparameters *p,double *o,double **s,TCuikSystem *cs)
4993 {
4994  if (UpdateCuikSystem(p,cs))
4996  else
4997  Error("Inconsistent input cuiksystem");
4998 
4999  return(cs->simp_nvariables);
5000 }
5001 
5002 unsigned int SimplifyBooleanArray(Tparameters *p,boolean *bo,boolean **bs,
5003  TCuikSystem *cs)
5004 {
5005  if (UpdateCuikSystem(p,cs))
5006  {
5007  unsigned int i,k;
5008 
5009  NEW(*bs,cs->simp_nvariables,boolean);
5010 
5011  k=0;
5012  for(i=0;i<cs->orig_nvariables;i++)
5013  {
5014  if (IsInSimple(i,cs->orig2s))
5015  {
5016  (*bs)[k]=bo[i];
5017  k++;
5018  }
5019  }
5020  if (k!=cs->simp_nvariables)
5021  Error("Wrong number of variables in SimplifyBooleanArray");
5022  }
5023  else
5024  Error("Inconsistent input cuiksystem");
5025 
5026  return(cs->simp_nvariables);
5027 }
5028 
5029 /*
5030  Selects one dimension along which to split box 'b'. The dimension can
5031  be selected according to the size or according to the error that each
5032  variable induce in each equation.
5033  This is similar to ComputeSplitDimInt but the output is an index in
5034  the original system and not in the simplified one
5035  */
5037 {
5038  Tbox bsimp;
5039  unsigned int d;
5040 
5041  if (!cs->scalar)
5042  Error("ComputeSplitDim only operates on scalar systems");
5043 
5044  if (UpdateCuikSystem(p,cs))
5045  {
5046  SimpleFromOriginal(b,&bsimp,cs->orig2sd);
5047  d=GetVarIDInOriginal(ComputeSplitDimInt(p,&bsimp,cs),cs->orig2sd);
5048  DeleteBox(&bsimp);
5049  }
5050  else
5051  d=NO_UINT;
5052 
5053  return(d);
5054 }
5055 
5056 /*
5057  Returns TRUE if point stored in vector 'v' is included in box 'b'
5058  Dummy variables are not taken into account in this procedure.
5059 */
5061 {
5062  unsigned int i,k,nv;
5063  double *val;
5064  boolean in;
5065 
5066  nv=NVariables(&(cs->orig_variables));
5067 
5068  if (nv!=GetBoxNIntervals(b))
5069  Error("Wrong box size in PointInSystemBox");
5070 
5071  k=0;
5072  in=TRUE;
5073  for(i=0;((in)&&(i<nv));i++)
5074  {
5075  if (!IsDummyVariable(i,&(cs->orig_variables)))
5076  {
5077  val=(double *)GetVectorElement(k,v);
5078  if (val==NULL)
5079  Error("Vector with incorrect number of elements in PointInSystemBox");
5080  in=IsInside(*val,0.0,GetBoxInterval(i,b));
5081  k++;
5082  }
5083  }
5084  return(in);
5085 }
5086 
5087 void EvaluateCSEquations(double *p,double *r,TCuikSystem *cs)
5088 {
5090 }
5091 
5092 void EvaluateSimpCSEquations(Tparameters *pr,double *p,double *r,TCuikSystem *cs)
5093 {
5094  if (!UpdateCuikSystem(pr,cs))
5095  Error("Inconsistent input cuiksystem");
5096 
5098 }
5099 
5100 void EvaluateSubSetSimpCSEquations(Tparameters *pr,boolean *se,double *p,double *r,TCuikSystem *cs)
5101 {
5102  if (!UpdateCuikSystem(pr,cs))
5103  Error("Inconsistent input cuiksystem");
5104 
5106 }
5107 
5108 void EvaluateCSJacobian(double *p,double ***J,TCuikSystem *cs)
5109 {
5110  TJacobian Ja;
5111 
5112  InitJacobian(&(cs->orig_variables),&(cs->orig_equations),&Ja);
5113 
5115  EvaluateJacobian(p,*J,&Ja);
5116 
5117  DeleteJacobian(&Ja);
5118 }
5119 
5120 double ErrorInCSEquations(double *p,TCuikSystem *cs)
5121 {
5122  double *r,e;
5123  unsigned int neq;
5124 
5125  neq=NEqualityEquations(&(cs->orig_equations));
5126  if (neq>0)
5127  {
5128  NEW(r,neq,double);
5129 
5131  e=Norm(neq,r);
5132  free(r);
5133  }
5134  else
5135  e=0.0;
5136 
5137  return(e);
5138 }
5139 
5141 {
5142  double *r,e;
5143  unsigned int neq;
5144 
5145  if (!UpdateCuikSystem(pr,cs))
5146  Error("Inconsistent input cuiksystem");
5147 
5148  neq=NEqualityEquations(&(cs->simp_equations));
5149  if (neq>0)
5150  {
5151  NEW(r,neq,double);
5153  e=Norm(neq,r);
5154  free(r);
5155  }
5156  else
5157  e=0.0;
5158 
5159  return(e);
5160 }
5161 
5162 double EvaluateCSCost(Tparameters *p,boolean simp,double *s,void *cs)
5163 {
5164  double v;
5165 
5166  if (simp)
5167  v=EvaluateWholeEquation(s,&(((TCuikSystem *)cs)->simp_eqMin));
5168  else
5169  v=EvaluateWholeEquation(s,&(((TCuikSystem *)cs)->orig_eqMin));
5170 
5171  return(v);
5172 }
5173 
5174 /*
5175  Takes the center of the box and computes the error of this
5176  point when replaced into the system of equations.
5177  We use this function to check the validity of the outputs
5178  of Cuik.
5179  */
5181 {
5182  double *p; /*central point of the box*/
5183  unsigned int i;
5184  double *r,maxError;
5185  //double e;
5186  unsigned int nv,neq;
5187 
5188  maxError=0;
5189 
5190  nv=NVariables(&(cs->orig_variables));
5191  neq=NEqualityEquations(&(cs->orig_equations));
5192  if ((nv>0)&&(neq>0))
5193  {
5194  if (nv!=GetBoxNIntervals(b))
5195  Error("Wrong box size in ErrorInSolution");
5196 
5197  NEW(p,nv,double);
5198 
5199  for(i=0;i<nv;i++)
5200  p[i]=IntervalCenter(GetBoxInterval(i,b));
5201 
5202  NEW(r,neq,double);
5204  maxError=Norm(neq,r);
5205  /*
5206  for(i=0;i<neq;i++)
5207  {
5208  e=fabs(r[i]);
5209  if (e>maxError)
5210  maxError=e;
5211  }
5212  */
5213  free(r);
5214  free(p);
5215  }
5216  return(maxError);
5217 }
5218 
5220 {
5221  unsigned int i,neq,nv;
5222  double maxError,*r,*p;
5223 
5224  nv=NVariables(&(cs->orig_variables));
5225 
5226  if (nv!=GetBoxNIntervals(b))
5227  Error("Wrong box size in ErrorInInequalities");
5228 
5230  if (neq>0)
5231  {
5232  NEW(p,nv,double);
5233  for(i=0;i<cs->orig_nvariables;i++)
5234  p[i]=IntervalCenter(GetBoxInterval(i,b));
5235 
5236  NEW(r,neq,double);
5238  maxError=MaxVector(neq,r);
5239  free(r);
5240  free(p);
5241  }
5242  else
5243  maxError=0.0;
5244 
5245  return(maxError);
5246 }
5247 
5248 boolean InequalitiesHoldOnPoint(double *p,TCuikSystem *cs)
5249 {
5250  unsigned int neq;
5251  boolean hold;
5252  double *r;
5253 
5255  if (neq>0)
5256  {
5257  NEW(r,neq,double);
5259  hold=(MaxVector(neq,r)==0.0);
5260  free(r);
5261  }
5262  else
5263  hold=TRUE;
5264 
5265  return(hold);
5266 }
5267 
5269 {
5270  unsigned int neq;
5271  boolean hold;
5272  double *r;
5273 
5274  if (!UpdateCuikSystem(pr,cs))
5275  Error("Inconsistent input cuiksystem");
5276 
5278  if (neq>0)
5279  {
5280  NEW(r,neq,double);
5282  hold=(MaxVector(neq,r)==0.0);
5283  free(r);
5284  }
5285  else
5286  hold=TRUE;
5287 
5288  return(hold);
5289 }
5290 
5292 {
5293  unsigned int neq;
5294  double e,*r;
5295 
5296  if (!UpdateCuikSystem(pr,cs))
5297  Error("Inconsistent input cuiksystem");
5298 
5300  if (neq>0)
5301  {
5302  NEW(r,neq,double);
5304  e=MaxVector(neq,r);
5305  free(r);
5306  }
5307  else
5308  e=0.0;
5309 
5310  return(e);
5311 }
5312 unsigned int ManifoldDimension(Tparameters *pr,double *p,TCuikSystem *cs)
5313 {
5314  double epsilon,*JT,error;
5315  double *pWithDummies,*pSimp;
5316  unsigned int nr,nc,k;
5317 
5318  if (!UpdateCuikSystem(pr,cs))
5319  Error("Inconsistent cuiksystem in ComputeSplitDimInt");
5320 
5321  if (cs->simp_nequations==0)
5322  Error("Empty simplified system in ManifoldDimension");
5323 
5324  epsilon=GetParameter(CT_EPSILON,pr);
5325 
5326  /* Convert from original point ot simplified point */
5327  RegenerateSolutionPoint(pr,p,&pWithDummies,cs);
5328  GenerateSimplifiedPoint(pr,pWithDummies,&pSimp,cs);
5329 
5330  /* We verify that the given point is a solution. Otherwise the rank estimation
5331  would be not valid. */
5332  error=ErrorInSimpCSEquations(pr,pSimp,cs);
5333  if (error>epsilon)
5334  Error("Point not in manifold");
5335 
5336  GetJacobianSize(&nr,&nc,&(cs->J));
5337 
5338  if ((nr==0)||(nc==0))
5339  Error("Empty jacobian in ManifoldDimension");
5340 
5341  NEW(JT,nc*nr,double);
5342 
5343  EvaluateTransposedJacobianInVector(pSimp,nc,nr,JT,&(cs->J));
5344 
5345  k=nc-FindRank(epsilon,nr,nc,JT);
5346 
5347  free(pWithDummies);
5348  free(pSimp);
5349  free(JT);
5350 
5351  return(k);
5352 }
5353 
5354 
5355 /*
5356  Prints the information stored in the cuiksystem
5357  It prints it in a form than can be parsed again.
5358 */
5360 {
5361  unsigned int nv;
5362  char **varNames;
5363 
5364  PrintVariables(f,&(cs->orig_variables));
5365 
5366  nv=NVariables(&(cs->orig_variables));
5367  NEW(varNames,nv,char *);
5368  GetVariableNames(varNames,&(cs->orig_variables));
5369  PrintEquations(f,varNames,&(cs->orig_equations));
5371  {
5372  fprintf(f,"\n[SEARCH]\n\n MIN ");
5373  PrintMonomials(f,varNames,&(cs->orig_eqMin));
5374  }
5375  free(varNames);
5376  fprintf(f,"\n\n");
5377 }
5378 
5379 /*
5380  Prints the information stored in the cuiksystem together with the simplified
5381  CuikSystem.
5382  It prints it in a form than can be parsed again.
5383 */
5385 {
5386  unsigned int nv;
5387  char **varNames;
5388 
5389  #if (_DEBUG>1)
5390  fprintf(f,"%%****************************************\n");
5391  fprintf(f,"%% Original system \n");
5392  PrintVariables(f,&(cs->orig_variables));
5393 
5394  nv=NVariables(&(cs->orig_variables));
5395  NEW(varNames,nv,char *);
5396  GetVariableNames(varNames,&(cs->orig_variables));
5397  PrintEquations(f,varNames,&(cs->orig_equations));
5399  {
5400  fprintf(f,"\n[SEARCH]\n\n MIN ");
5401  PrintMonomials(f,varNames,&(cs->orig_eqMin));
5402  }
5403  fprintf(f,"\n\n");
5404  free(varNames);
5405  #endif
5406 
5407  if (UpdateCuikSystem(p,cs))
5408  {
5409  fprintf(f,"%%****************************************\n");
5410  fprintf(f,"%% Simplified system \n");
5411  fprintf(f,"%% SIMPLIFICATION_LEVEL: %u\n",
5412  (unsigned int)(GetParameter(CT_SIMPLIFICATION_LEVEL,p)));
5413  fprintf(f,"%% Variable reduction %u -> %u\n",cs->orig_nvariables,
5414  cs->simp_nvariables);
5415  fprintf(f,"%% Num syst+secu variables in original : %u \n",
5418  fprintf(f,"%% Num syst+secu variables in simplified: %u \n",
5421  PrintMapping(f,cs->orig2sd);
5422  PrintVariables(f,&(cs->variables));
5423 
5424  nv=NVariables(&(cs->variables));
5425  NEW(varNames,nv,char *);
5426  GetVariableNames(varNames,&(cs->variables));
5427  PrintEquations(f,varNames,&(cs->equations));
5429  {
5430  fprintf(f,"\n[SEARCH]\n\n MIN ");
5431  PrintMonomials(f,varNames,&(cs->eqMin));
5432  }
5433  free(varNames);
5434  }
5435  else
5436  fprintf(f,"INCONSISTENT INPUT CUIK SYSTEM\n");
5437 }
5438 
5440 {
5441  if (UpdateCuikSystem(p,cs))
5442  SaveMapping(f,cs->orig2sd);
5443  else
5444  fprintf(f,"INCONSISTENT INPUT CUIK SYSTEM\n");
5445 }
5446 
5447 /*
5448  Destructor of the cuiksystem structure.
5449 */
5451 {
5452  DeleteConstants(&(cs->constants));
5453 
5456  DeleteStatistics(&(cs->st));
5457 
5458  DeleteEquation(&(cs->orig_eqMin));
5459 
5460  UnUpdateCuikSystem(cs);
5461 
5462  cs->empty=TRUE;
5463  cs->simp_empty=TRUE;
5464 }
unsigned int SimplexNRows(TSimplex *s)
Gets the number of rows (i.e., constraints) of the simplex structure.
Definition: simplex_clp.c:107
Definition of the boolean type.
boolean PointInBox(boolean *used, unsigned int n, double *v, double tol, Tbox *b)
Checks if a point is included in a(sub-) box.
Definition: box.c:356
void First(Titerator *i)
Moves an iterator to the first position of its associated list.
Definition: list.c:356
double MaxVector(unsigned int m, double *v)
Value of the maximum element of a vector.
double EvaluateEqMin(void *b, void *cs)
Evaluates the equation to minimize in a given box.
Definition: cuiksystem.c:2384
Set of variables of a cuiksystem.
Definition: variables.h:38
void PrintCuikSystemWithSimplification(Tparameters *p, FILE *f, TCuikSystem *cs)
Prints the simplified cuiksystem.
Definition: cuiksystem.c:5384
void Box2Buffer(unsigned int c, unsigned int n, double *buffer, Tbox *b)
Converts a box into an array of doubles.
Definition: box.c:81
void InitConstants(Tconstants *cts)
Initializes a constant set.
Definition: constants.c:21
void DeleteLinearConstraint(TLinearConstraint *lc)
Destructor.
#define CARTESIAN_VAR
One of the possible type of variables.
Definition: variable.h:62
void RewriteEquation2Simp(double epsilon, Tmapping *map, Tequation *eqOut, Tequation *eq)
Applies the simplification mapping to an equation.
Definition: equation.c:237
Tequation * GetScalarEquation(unsigned int n, Tequations *eqs)
Gets a scalar equation from the set.
Definition: equations.c:1791
Tinterval * GetBoxInterval(unsigned int n, Tbox *b)
Returns a pointer to one of the intervals defining the box.
Definition: box.c:270
void SetCSVariableRange(unsigned int n, Tinterval *r, TCuikSystem *cs)
Gets the range of a variable from a cuiksystem.
Definition: cuiksystem.c:2595
double EvaluateWholeEquation(double *varValues, Tequation *eq)
Evaluates an equation in a given point.
Definition: equation.c:1726
#define ERROR_IN_PROCESS
One of the possible results of reducing a box.
Definition: box.h:32
void EvaluateSubSetSimpCSEquations(Tparameters *pr, boolean *se, double *p, double *r, TCuikSystem *cs)
Evaluates a subset of the simplified equation set on a point.
Definition: cuiksystem.c:5100
#define SYSTEM_EQ
One of the possible type of equations.
Definition: equation.h:146
Tequation * GetEquation(unsigned int n, Tequations *eqs)
Gets an equation from the set.
Definition: equations.c:1799
boolean IsCSPolynomial(TCuikSystem *cs)
Identifies polynomial cuiksystems.
Definition: cuiksystem.c:2696
Tmonomial * GetMonomial(unsigned int i, Tequation *eq)
Gets a monomial from an equation.
Definition: equation.c:1695
void InitJacobian(Tvariables *vs, Tequations *eqs, TJacobian *j)
Constructor.
Definition: jacobian.c:16
double DistanceToInterval(double p, Tinterval *i)
Distance to an interval.
Definition: interval.c:112
#define CT_EPSILON
Numerical tolerance.
Definition: parameters.h:194
unsigned int NEquations(Tequations *eqs)
Number of equations in the set.
Definition: equations.c:1164
#define FALSE
FALSE.
Definition: boolean.h:30
void SaveMapping(FILE *f, Tmapping *m)
Saves the mapping information into a file.
Definition: csmapping.c:291
boolean SampleCuikSystem(Tparameters *p, char *fname, Tlist *sb, unsigned int nsamples, unsigned int ntries, unsigned int ndof, TCuikSystem *cs)
Generates samples for a cuiksystem.
Definition: cuiksystem.c:2988
double GetTime(Tstatistics *t)
Curent time.
Definition: statistics.c:74
#define CONVERGED_OUTSIDE_GLOBAL
One of the possible outputs of the Newton iteration.
Definition: cuiksystem.h:150
unsigned int ManifoldDimension(Tparameters *pr, double *p, TCuikSystem *cs)
Computes the dimension of the solution space.
Definition: cuiksystem.c:5312
boolean IsSecondaryVariable(unsigned int n, Tvariables *vs)
Identifies secondary variables in a set.
Definition: variables.c:108
unsigned int NVariables(Tvariables *vs)
Gets the number of variables in a set.
Definition: variables.c:69
unsigned int SimplifyBooleanArray(Tparameters *p, boolean *bo, boolean **bs, TCuikSystem *cs)
Transforms arrays of booleans from the original to the simplified system.
Definition: cuiksystem.c:5002
unsigned int ComputeSplitDimInt(Tparameters *p, Tbox *b, TCuikSystem *cs)
Computes the optimal split dimension for a given box.
Definition: cuiksystem.c:1984
boolean SimplifiedMEquation(TMequation *me)
Identifies simplified equations.
Definition: mequation.c:353
unsigned int GetVariableTypeN(unsigned int n, Tvariables *vs)
Gets the type of a particular variable.
Definition: variables.c:123
void SetEquationType(unsigned int type, Tequation *eq)
Changes the type of the equation (SYSTEM_EQ, CARTESIAN_EQ, DUMMY_EQ, DERIVED_EQ). ...
Definition: equation.c:1076
unsigned int GetCSNumEquations(TCuikSystem *cs)
Gets the number of equations already in the cuiksystem.
Definition: cuiksystem.c:2709
boolean IsCoordEquation(unsigned int i, Tequations *eqs)
Identify coordenalization equations.
Definition: equations.c:1220
void GetVariableNames(char **varNames, Tvariables *vs)
Gets the name for all the variables in the set.
Definition: variables.c:234
#define NEW(_var, _n, _type)
Allocates memory space.
Definition: defines.h:385
double GetBoxSize(boolean *used, Tbox *b)
Computes the size of the box.
Definition: box.c:631
void EvaluateTransposedJacobianInVector(double *v, unsigned int nr, unsigned int nc, double *m, TJacobian *j)
Evaluates the transposed Jacobian.
Definition: jacobian.c:143
Data structure to hold the information about the name of a file.
Definition: filename.h:271
#define RC2INDEX(i, j, nr, nc)
Index in a vector of a matrix element.
Definition: basic_algebra.h:81
#define CUT_POINT
Point, relative to the size of the selected box side, where we split a box.
Definition: cuiksystem.h:88
void ArrayPi2Pi(unsigned int n, unsigned int *t, double *a)
Applies PI2PI to an array.
unsigned int ReduceBoxEquationWise(Tparameters *p, Tbox *b, TCuikSystem *cs)
Reduces a box considering one equation at a time.
Definition: cuiksystem.c:714
void NewLostBox(Tstatistics *t)
Increases the number of lost boxes.
Definition: statistics.c:173
void EvaluateEquationInt(Tinterval *varValues, Tinterval *i_out, Tequation *eq)
Interval evaluation of an equation.
Definition: equation.c:1760
A linear constraint with an associated error.
Tequations orig_equations
Definition: cuiksystem.h:242
boolean * systemVar
Definition: cuiksystem.h:209
void DeleteEquation(Tequation *eq)
Destructor.
Definition: equation.c:1859
unsigned int GetVarIDInOriginal(unsigned int v, Tmapping *m)
Gets the original identifier of a simplified variable.
Definition: csmapping.c:135
#define CT_SMALL_SIGMA
Box size threshold.
Definition: parameters.h:229
void EvaluateJacobian(double *v, double **m, TJacobian *j)
Evaluates the Jacobian.
Definition: jacobian.c:85
boolean IsCartesianVariable(unsigned int n, Tvariables *vs)
Identifies cartesian variables in a set.
Definition: variables.c:118
void GenerateInitialBox(Tbox *box, TCuikSystem *cs)
Gives the search space in the form of a box.
Definition: cuiksystem.c:4849
void * GetVectorElement(unsigned int i, Tvector *vector)
Returns a pointer to a vector element.
Definition: vector.c:270
void SaveStatistics(FILE *f, Tstatistics *t)
Saves the statistics to a file in binary format.
Definition: statistics.c:260
void AddMatrixEquation(TMequation *equation, Tequations *eqs)
Adds a matrix equation to the set.
Definition: equations.c:1759
#define CT_SPLIT_TYPE
Split type.
Definition: parameters.h:346
unsigned int randomMax(unsigned int m)
Returns a random integer in the range [0,m].
Definition: random.c:77
void SetBoxInterval(unsigned int n, Tinterval *is, Tbox *b)
Replaces a particular interval in a box.
Definition: box.c:259
void SaveCSState(char *fname, Tlist *lb, TCuikSystem *cs)
Saves internal the cuik solver state information to a file.
Definition: cuiksystem.c:2105
boolean IncrementalSampleCuikSystem(Tparameters *p, char *fname, Tlist *sb, boolean *fixVars, unsigned int nsamples, unsigned int ntries, unsigned int ndof, TCuikSystem *cs)
Generates samples for a cuiksystem.
Definition: cuiksystem.c:3265
void MergeEquations(Tequations *eqs1, Tequations *eqs)
Copy constructor.
Definition: equations.c:802
boolean * orig_notDummyVar
Definition: cuiksystem.h:254
#define NEWZ(_var, _n, _type)
Allocates and cleans memory space.
Definition: defines.h:394
Tvariables simp_variables
Definition: cuiksystem.h:226
Collection of methods to work on Theap of boxes.
void ResetNBoxReductions(Tstatistics *t)
Resets the number of reduced boxes.
Definition: statistics.c:196
#define SYSTEM_VAR
One of the possible type of variables.
Definition: variable.h:24
void InitStatistics(unsigned int np, double v, Tstatistics *t)
Constructor.
Definition: statistics.c:21
CBLAS_INLINE double Norm(unsigned int s, double *v)
Computes the norm of a vector.
unsigned int AddVariable2CS(Tvariable *v, TCuikSystem *cs)
Adds a variable to the system.
Definition: cuiksystem.c:2532
void AddBox2HeapOfBoxes(Tbox *b, Theap *h)
Adds a box to a heap of boxes.
Definition: box_heap.c:26
void LoadStatistics(FILE *f, Tstatistics *t)
Loads the statistics from a file in binary format.
Definition: statistics.c:266
void CopyEquation(Tequation *eq_dst, Tequation *eq_orig)
Copy constructor.
Definition: equation.c:216
void CopyEquations(Tequations *eqs_dst, Tequations *eqs_src)
Copy constructor.
Definition: equations.c:755
double GetBoxSumSide(boolean *used, Tbox *b)
Computes the sum of the sides of the box.
Definition: box.c:998
void NewEmptyBox(Tstatistics *t)
Increases the number of empty boxes.
Definition: statistics.c:147
char ** orig_varNames
Definition: cuiksystem.h:256
#define CT_LR2TM_S
Threshold to switch from linear relaxations to Taylor models for saddle equations.
Definition: parameters.h:398
#define DEPTH_FIRST_SEARCH
Depth first search.
Definition: cuiksystem.h:54
void DeleteJacobian(TJacobian *j)
Destructor.
Definition: jacobian.c:255
void NewBoxReduction(Tstatistics *t)
Increases the number of reduced boxes.
Definition: statistics.c:181
double HeapOfBoxesVolume(boolean *used, Theap *h)
Computes the volume of a heap.
Definition: box_heap.c:31
double ErrorInSimpCSEquations(Tparameters *pr, double *p, TCuikSystem *cs)
Evaluates the norm of the error in a point for the simplified equations.
Definition: cuiksystem.c:5140
#define EQU
In a Tequation, the equation relational operator is equal.
Definition: equation.h:202
void SetOriginalVarRelation(unsigned int nvo, TLinearConstraint *lc, Tmapping *m)
Set a relation for a variable in the original set.
Definition: csmapping.c:100
#define DUMMY_EQ
One of the possible type of equations.
Definition: equation.h:164
void InitLinearConstraint(TLinearConstraint *lc)
Constructor.
void SaveCuikSystemSimplification(Tparameters *p, FILE *f, TCuikSystem *cs)
Saves the simplification information associated with a cuiksystem.
Definition: cuiksystem.c:5439
void AddSimplifiedJacobianEquations(Tparameters *p, boolean *selectedVars, TCuikSystem *cs)
Adds a linear combination of the Jacobian to the system.
Definition: cuiksystem.c:2835
void UpdateSplitWeight(unsigned int ne, double *splitDim, Tbox *b, Tequations *eqs)
Computes the linearization error induced by the variables of a given equation.
Definition: equations.c:2532
void DeleteCuikSystem(TCuikSystem *cs)
Destructor.
Definition: cuiksystem.c:5450
boolean LinearConstraintIncludes(unsigned int ind, TLinearConstraint *lc)
Checks if a variable is included in a linear constraint.
unsigned int GetCSSystemVars(boolean **sv, TCuikSystem *cs)
Identifies the system variables.
Definition: cuiksystem.c:2659
void UnUpdateCuikSystem(TCuikSystem *cs)
Removes the cached information for the cuiksystem.
Definition: cuiksystem.c:1767
Tequation * GetJacobianEquation(unsigned int r, unsigned int c, TJacobian *j)
Returns one element of the Jacobian.
Definition: jacobian.c:63
char * GetCSVariableName(unsigned int id, TCuikSystem *cs)
Gets a variable name.
Definition: cuiksystem.c:2612
boolean CuikGradient(Tparameters *p, double *sol, Tbox *b_sol, TCuikSystem *cs)
Applies gradient descent to a set of equations.
Definition: cuiksystem.c:4171
#define EMPTY_BOX
One of the possible results of reducing a box.
Definition: box.h:25
void AllocateJacobianEvaluation(double ***m, TJacobian *j)
Allocate space for the Jacobian evaluation.
Definition: jacobian.c:71
Tequations equations
Definition: cuiksystem.h:204
unsigned int GetNBoxReductions(Tstatistics *t)
Gets the number of reduced boxes.
Definition: statistics.c:186
unsigned int ReduceBox(Tparameters *p, unsigned int varMask, Tbox *b, TCuikSystem *cs)
Reduces a box as much as possible.
Definition: cuiksystem.c:833
Definition of the Tfilename type and the associated functions.
#define BREADTH_FIRST_SEARCH
Breadth first search.
Definition: cuiksystem.h:63
void InitVariables(Tvariables *vs)
Constructor.
Definition: variables.c:24
unsigned int GetLinearConstraintVariable(unsigned int i, TLinearConstraint *lc)
Gets the a particular variable index.
void RegenerateOriginalBox(Tparameters *p, Tbox *boxS, Tbox *boxO, TCuikSystem *cs)
Generates a box in the original cuiksystem from a box of the simplified one.
Definition: cuiksystem.c:4967
unsigned int NInequalityEquations(Tequations *eqs)
Number of inequalities in the set.
Definition: equations.c:1194
void PrintLinearConstraint(FILE *f, boolean eq, char **varName, TLinearConstraint *lc)
Prints a linear constraint.
void SetVariableInterval(Tinterval *i, Tvariable *v)
Sets the new range for the variable.
Definition: variable.c:68
#define TRUE
TRUE.
Definition: boolean.h:21
Mapping between the sets of variables in two different cuiksystems.
Definition: csmapping.h:53
double * GetNewtonRHBuffer(TNewton *n)
Buffer to store the Newton right hand.
Definition: algebra.c:1152
boolean CmpBoxBreadthFirst(void *b1, void *b2, void *userData)
Determines which box to explore first in breadth first mode.
Definition: box.c:1134
unsigned int searchMode
Definition: cuiksystem.h:193
void InitBox(unsigned int dim, Tinterval *is, Tbox *b)
Initializes a box.
Definition: box.c:23
#define CT_SAFE_SIMPLEX
Trade off between speed and numerical stability when using the simplex.
Definition: parameters.h:358
void PointFromVariables(double **p, Tvariables *vs)
Creates a point from the center of the ranges of a set of variables.
Definition: variables.c:294
Tmapping * orig2sd
Definition: cuiksystem.h:202
void InitEquation(Tequation *eq)
Constructor.
Definition: equation.c:86
void Error(const char *s)
General error function.
Definition: error.c:80
void AddMatrixEquation2CS(Tparameters *p, TMequation *eq, TCuikSystem *cs)
Adds a matrix equation to the system.
Definition: cuiksystem.c:2511
#define NFUN
No trigonometric function for the variable.
Definition: variable_set.h:36
#define TOPOLOGY_R
One of the possible topologies.
Definition: defines.h:122
void SetBoxSubset(boolean *used, Tbox *bset, Tbox *b)
Changes a sub-set of ranges in a given box.
Definition: box.c:238
void RemoveVariable(unsigned int n, Tvariables *vs)
Removes a variable from a set.
Definition: variables.c:257
boolean AddEquation2Simplex(unsigned int ne, double lr2tm_q, double lr2tm_s, double epsilon, unsigned int safeSimplex, double rho, Tbox *b, Tvariables *vs, TSimplex *lp, Tequations *eqs)
Adds an equation to the simplex.
Definition: equations.c:2287
void GetJacobianSize(unsigned int *nr, unsigned int *nc, TJacobian *j)
Returns the size of the Jacobian.
Definition: jacobian.c:49
void CuikSystemMerge(Tparameters *p, TCuikSystem *cs1, TCuikSystem *cs2, TCuikSystem *cs)
Produces the union of two cuik systems.
Definition: cuiksystem.c:2335
void CSRemoveUnusedVars(Tparameters *p, TCuikSystem *cs)
Removes non-used variables.
Definition: cuiksystem.c:1260
unsigned int orig_nequations
Definition: cuiksystem.h:245
#define CT_SIGMA
Box size threshold.
Definition: parameters.h:236
boolean simp_empty
Definition: cuiksystem.h:223
#define MINIMIZATION_SEARCH
Search based on a minimum value of a given equation.
Definition: cuiksystem.h:76
boolean UpdateCuikSystem(Tparameters *p, TCuikSystem *cs)
Updates the cached information for the cuiksystem.
Definition: cuiksystem.c:1852
void GetCSVariable(unsigned int n, Tvariable *v, TCuikSystem *cs)
Gets the a variable from a cuiksystem.
Definition: cuiksystem.c:2587
void EvaluateCSEquations(double *p, double *r, TCuikSystem *cs)
Evaluates the equation set on a point.
Definition: cuiksystem.c:5087
#define CONVERGED_IN_BOX
One of the possible outputs of the Newton iteration.
Definition: cuiksystem.h:124
A simplex tableau structure.
Definition: simplex.h:73
unsigned int CropEquation(unsigned int ne, unsigned int varType, double epsilon, double rho, Tbox *b, Tvariables *vs, Tequations *eqs)
Equation-wise crop.
Definition: equations.c:1269
#define ZERO
Floating point operations giving a value below this constant (in absolute value) are considered 0...
Definition: defines.h:37
void AddTerm2LinearConstraint(unsigned int ind, double val, TLinearConstraint *lc)
Adds a scaled variable to the linear constraint.
unsigned int GetBoxBufferSize(Tbox *b)
Returns the size of a box when converted to an array of doubles.
Definition: box.c:76
Matrix equation.
Definition: mequation.h:42
void Crop2Box(boolean *used, unsigned int n, double *p, Tbox *b)
Forces a point to be inside a box.
Definition: box.c:328
void SetEquationValue(double v, Tequation *eq)
Changes the right-hand value of the equation.
Definition: equation.c:1089
void AddNBoxReductions(unsigned int nr, Tstatistics *t)
Increases the number of reduced boxes.
Definition: statistics.c:201
Collection of methods to work on Tlist of boxes.
void VariablesFromBox(Tbox *b, Tvariables *vs)
Define the range for the variables from a box.
Definition: variables.c:305
unsigned int GetSimpCSTopology(Tparameters *p, unsigned int **t, TCuikSystem *cs)
Topology of the variables in the simplified system.
Definition: cuiksystem.c:2719
void AddMonomial(Tmonomial *f, Tequation *eq)
Adds a new monomial to the equation.
Definition: equation.c:1419
void SimplexCreate(double epsilon, unsigned int ncols, TSimplex *s)
Constructor.
Definition: simplex_clp.c:22
void CopyConstants(Tconstants *cts_dst, Tconstants *cts_src)
Copies a set of constants.
Definition: constants.c:30
void DeleteMapping(Tmapping *m)
Destructor.
Definition: csmapping.c:310
boolean VarIncluded(unsigned int id, Tvariable_set *vs)
Checks if a variable index is included in a set of variable indexes.
Definition: variable_set.c:183
unsigned int GetVariableFunctionN(unsigned int n, Tvariable_set *vs)
Gets a variable function from a variable set.
Definition: variable_set.c:481
void AddTerm2SearchCriterion(double w, unsigned int v, double val, TCuikSystem *cs)
Adds penalty terms to the search criterion.
Definition: cuiksystem.c:2456
unsigned int GetBoxNIntervals(Tbox *b)
Box dimensionality.
Definition: box.c:1016
void CopyCuikSystem(TCuikSystem *cs_dst, TCuikSystem *cs_src)
Copy constructor.
Definition: cuiksystem.c:2216
void MPI_TreatBox(Tparameters *p, TCuikSystem *cs)
Determines the solution set for a cuiksystem. Child process.
Definition: cuiksystem.c:4756
boolean IsSimplificable(unsigned int simpLevel, unsigned int nTerms, boolean polynomial, boolean *systemVars, Tbox *cb, unsigned int *v, TLinearConstraint *lc, Tequation *eq)
Identify equations than can trigger variable simplifications.
Definition: equation.c:851
boolean IsSystemVariable(unsigned int n, Tvariables *vs)
Identifies system variables in a set.
Definition: variables.c:103
unsigned int GetBoxLevel(Tbox *b)
Returns the box level.
Definition: box.c:700
int NewtonStep(double nullSingularValue, double *x, double *dif, TNewton *n)
One step in a Newton iteration.
unsigned int GetVariableN(unsigned int n, Tvariable_set *vs)
Gets a variable identifier from a variable set.
Definition: variable_set.c:454
Error and warning functions.
void UpdateOriginalPointFromSimple(double *s, double *o, Tmapping *m)
Gets a original point from an simplified one.
Definition: csmapping.c:199
void DeleteFileName(Tfilename *fn)
Destructor.
Definition: filename.c:205
void CopyVariables(Tvariables *vs_dst, Tvariables *vs_src)
Copy onstructor.
Definition: variables.c:40
void SolveCuikSystem(Tparameters *p, boolean restart, char *fstate, Tbox *searchSpace, FILE *f_out, Tlist *sol, TCuikSystem *cs)
Determines the solution set for a cuiksystem.
Definition: cuiksystem.c:4192
unsigned int FindRank(double epsilon, unsigned int nr, unsigned int nc, double *mT)
Determines the row-rank of a matrix.
Definition: algebra.c:1105
unsigned int MaxReduction(Tparameters *p, unsigned int varMask, double *reduction, Tbox *b, TCuikSystem *cs)
Reduces a box as much as possible.
Definition: cuiksystem.c:2955
double ErrorInCSEquations(double *p, TCuikSystem *cs)
Evalates the norm of the error in a point.
Definition: cuiksystem.c:5120
void ResetSimplex(TSimplex *s)
Resets the simplex structure.
Definition: simplex_clp.c:96
unsigned int ReduceRange(double epsilon, unsigned int safeSimplex, unsigned int nv, Tbox *b, TSimplex *lp)
Reduces a variable range using the simplex.
Definition: simplex.c:329
void InitMapping(Tvariables *o, Tvariables *s, Tmapping *m)
Constructor.
Definition: csmapping.c:14
#define MPI_TREAT_BOX_TIMEOUT(cs)
MPI child-process timeout.
Definition: cuiksystem.h:100
boolean PointInSystemBox(Tvector *v, Tbox *b, TCuikSystem *cs)
Determines if a given point is fully included in the system sub-box (i.e., the sub-box fot the system...
Definition: cuiksystem.c:5060
boolean scalar
Definition: cuiksystem.h:188
void DeleteListOfBoxes(Tlist *l)
Destructor.
Definition: box_list.c:353
void AddLastElement(void *Info, Tlist *list)
Adds an element at the tail of the list.
Definition: list.c:206
Tstatistics st
Definition: cuiksystem.h:190
void PrintEquation(FILE *f, char **varNames, Tequation *eq)
Prints an equation.
Definition: equation.c:1825
void SetEquationCmp(unsigned int cmp, Tequation *eq)
Changes the relational operator (LEQ, GEQ, EQU) of the equation.
Definition: equation.c:1081
void CopyLinearConstraint(TLinearConstraint *lc_dst, TLinearConstraint *lc_src)
Copy constructor.
void CopyVariable(Tvariable *v_dst, Tvariable *v_src)
Copy constructor.
Definition: variable.c:31
void ResetMonomial(Tmonomial *f)
Reset the monomial information.
Definition: monomial.c:24
boolean IncrementalSampleCuikSystemInBox(Tparameters *p, char *fname, Tlist *sb, boolean *fixVars, unsigned int nsamples, unsigned int ntries, unsigned int ndof, Tbox *init_box, TCuikSystem *cs)
Generates samples for a cuiksystem in given box.
Definition: cuiksystem.c:3285
double LowerLimit(Tinterval *i)
Gets the lower limit.
Definition: interval.c:79
unsigned int GetVariablePowerN(unsigned int n, Tvariable_set *vs)
Gets a variable power from a variable set.
Definition: variable_set.c:470
unsigned int * simp_tp
Definition: cuiksystem.h:232
unsigned int ComputeSplitDim(Tparameters *p, Tbox *b, TCuikSystem *cs)
Determines the best dimensions to split a given box.
Definition: cuiksystem.c:5036
unsigned int GetNumSecondaryVariables(Tvariables *vs)
Gets the number of secondary variables in a set.
Definition: variables.c:98
void RemoveEquationsWithVar(double epsilon, unsigned int nv, Tequations *eqs)
Removes all equations that include a given variable.
Definition: equations.c:869
void GenerateGeneralNormEquation(unsigned int nv, unsigned int *v, double n, Tequation *eq)
Construtor. Generates an equation that is the norm of a vector.
Definition: equation.c:1506
unsigned int NEqualityEquations(Tequations *eqs)
Number of equalities in the set.
Definition: equations.c:1189
void EvaluateJacobianInVector(double *v, unsigned int nr, unsigned int nc, double *m, TJacobian *j)
Evaluates the Jacobian.
Definition: jacobian.c:103
Tvariables orig_variables
Definition: cuiksystem.h:243
unsigned int GetVariableID(char *name, Tvariables *vs)
Gets the variable identifier (i.e., its position in the set) given a variable name.
Definition: variables.c:201
void DummifyAndAddEquation(Tparameters *p, Tequation *eq, TCuikSystem *cs)
Adds an equation to the cuiksystem.
Definition: cuiksystem.c:422
Set of equations.
Definition: equations.h:81
boolean empty
Definition: cuiksystem.h:187
boolean IsDummyVariable(unsigned int n, Tvariables *vs)
Identifies dummy variables in a set.
Definition: variables.c:113
void PrintStatistics(FILE *f, Tstatistics *t)
Prints the statistics to a file.
Definition: statistics.c:209
unsigned int HeapSize(Theap *heap)
Gets the number of elements in a heap.
Definition: heap.c:284
boolean EndOfList(Titerator *i)
Checks if an iterator is pointing at the end of the list.
Definition: list.c:445
void VarScaleEquation(unsigned int v, Tequation *eq)
Scales an equation with a variable factor.
Definition: equation.c:680
An equation.
Definition: equation.h:237
void DeleteVariable(Tvariable *v)
Destructor.
Definition: variable.c:93
#define CT_LR2TM_Q
Threshold to switch from linear relaxations to Taylor models for quadratic equations.
Definition: parameters.h:389
boolean consistent
Definition: cuiksystem.h:185
unsigned int NScalarEquations(Tequations *eqs)
Number of scalar equations in the set.
Definition: equations.c:1169
Definitions of constants and macros used in several parts of the cuik library.
unsigned int AddVariable(Tvariable *v, Tvariables *vs)
Adds a variable to the set.
Definition: variables.c:138
unsigned int GetVariableTopology(Tvariable *v)
Gets the topology of the variable.
Definition: variable.c:50
A generic list.
Definition: list.h:46
boolean RegenerateSolution(Tparameters *p, Tbox *b, TCuikSystem *cs)
Regenerates a box from the system variables.
Definition: cuiksystem.c:4862
boolean IsCSScalar(TCuikSystem *cs)
Identifies scalar cuiksystems.
Definition: cuiksystem.c:2701
void InitIterator(Titerator *i, Tlist *list)
Constructor.
Definition: list.c:284
void SplitBox(unsigned int n, double r, Tbox *b1, Tbox *b2, Tbox *b)
Splits a box.
Definition: box.c:1064
boolean ParabolaEquation(Tequation *eq)
Identify scaled parabola equations.
Definition: equation.c:1184
void GetCSJacobian(TJacobian *J, TCuikSystem *cs)
Defines the Jacobian of a CuikSystem.
Definition: cuiksystem.c:2714
void EvaluateEqualitySparseEquations(double *v, double *r, Tequations *eqs)
Evaluates the set of equality equations for sparse systems.
Definition: equations.c:2675
unsigned int RegenerateSolutionPoint(Tparameters *p, double *pt, double **rp, TCuikSystem *cs)
Regenerates a solution point from the system variables.
Definition: cuiksystem.c:4926
void NewVariable(unsigned int type, char *name, Tvariable *v)
Constructor.
Definition: variable.c:20
void EvaluateEqualityEquations(boolean systemOnly, double *v, double *r, Tequations *eqs)
Evaluates all equality equations in the set.
Definition: equations.c:2579
void InitEquations(Tequations *eqs)
Constructor.
Definition: equations.c:720
void ScaleLinearConstraint(double a, TLinearConstraint *lc)
Scales a linear constraint.
double RemoveTermFromLinearConstraint(unsigned int ind, TLinearConstraint *lc)
Removes a variable from a linear constraint.
Tmapping * orig2s
Definition: cuiksystem.h:221
void GetCSEquations(Tequations *eqs, TCuikSystem *cs)
Gets a copy of the system equations.
Definition: cuiksystem.c:2680
void CopyStatistics(Tstatistics *t_dst, Tstatistics *t_src)
Copy constructor.
Definition: statistics.c:45
void CopyBox(void *b_out, void *b_in)
Box copy operator.
Definition: box.c:160
TJacobian J
Definition: cuiksystem.h:238
Tequation orig_eqMin
Definition: cuiksystem.h:194
#define CONVERGED_IN_GLOBAL
One of the possible outputs of the Newton iteration.
Definition: cuiksystem.h:138
boolean HeapEmpty(Theap *heap)
Checks if a heap is empty.
Definition: heap.c:289
A set of variable indexes with powers.
Definition: variable_set.h:139
Tvariable_set * GetMonomialVariables(Tmonomial *f)
Gets the variables of a monomial.
Definition: monomial.c:153
void InitCuikSystem(TCuikSystem *cs)
Constructor.
Definition: cuiksystem.c:2167
boolean CuikNewton(Tparameters *p, double *sol, Tbox *b_sol, TCuikSystem *cs)
Applies Newton-Rhapson to a set of equations.
Definition: cuiksystem.c:3947
void AddEquation2CS(Tparameters *p, Tequation *eq, TCuikSystem *cs)
Adds an equation to the system.
Definition: cuiksystem.c:2502
void DeleteHeap(Theap *heap)
Destructor.
Definition: heap.c:388
A scaled product of powers of variables.
Definition: monomial.h:32
void CacheScalarEQUInfo(Tequations *eqs)
Collects information about scalar equality equations.
Definition: equations.c:2643
#define ANY_TYPE_VAR
Union of variables of any type.
Definition: variable.h:68
void Warning(const char *s)
General warning function.
Definition: error.c:116
A table of parameters.
boolean CSRemoveLCVars(Tparameters *p, unsigned int simplificationLevel, unsigned int level, boolean *changed, boolean *replaced, TLinearConstraint *lc, Tbox *borig, TCuikSystem *cs)
Removes variables that are linearly dependent on other variables.
Definition: cuiksystem.c:1371
Definition of the TCuikSystem type and the associated functions.
void DeleteNewton(TNewton *n)
Releases a Newton structure.
boolean updated
Definition: cuiksystem.h:184
void Buffer2Box(unsigned int *c, unsigned int *n, double *buffer, Tbox *b)
Converts a buffer of doubles into a box.
Definition: box.c:122
void CreateFileName(char *path, char *name, char *suffix, char *ext, Tfilename *fn)
Constructor.
Definition: filename.c:22
unsigned int CuikNewtonSimp(Tparameters *p, double *x, TCuikSystem *cs)
CuikNewton on the simplified system.
Definition: cuiksystem.c:3618
boolean PolynomialEquations(Tequations *eqs)
Identify polynomial system of equations.
Definition: equations.c:1199
void UpdateOriginalFromSimple(Tbox *s, Tbox *o, Tmapping *m)
Gets a original box from an simplified one.
Definition: csmapping.c:177
unsigned int CuikNewtonInBox(Tparameters *p, Tbox *bIn, double *sol, Tbox *b_sol, TCuikSystem *cs)
Applies Newton-Rhapson to a set of equations.
Definition: cuiksystem.c:3714
boolean InequalitiesHoldOnPoint(double *p, TCuikSystem *cs)
Tests if all inqualities hold for a given point.
Definition: cuiksystem.c:5248
#define CT_RHO
Reduction threshold.
Definition: parameters.h:222
double GetBoxDiagonal(boolean *used, Tbox *b)
Computes the diagonal of a (sub-)box.
Definition: box.c:678
char * GetCSSystemVariableName(unsigned int id, TCuikSystem *cs)
Gets a system variable name.
Definition: cuiksystem.c:2617
void AddEquation(Tequation *equation, Tequations *eqs)
Adds an equation to the set.
Definition: equations.c:1723
unsigned int GetCSNumSystemVariables(TCuikSystem *cs)
Gets the number of system variables already in the cuiksystem.
Definition: cuiksystem.c:2570
A generic vector.
Definition: vector.h:227
boolean BoxInclusion(boolean *used, Tbox *b1, Tbox *b2)
Checks if a (sub-)box is fully included in another box.
Definition: box.c:610
void AddJacobianEquations(Tparameters *p, boolean *selectedVars, TCuikSystem *cs)
Adds linear a linear combination of the Jacobian to the system.
Definition: cuiksystem.c:2805
char * GetFileFullName(Tfilename *fn)
Gets the file full name (paht+name+extension).
Definition: filename.c:151
void PrintMapping(FILE *f, Tmapping *m)
Prints a mapping.
Definition: csmapping.c:218
Tequation eqMin
Definition: cuiksystem.h:216
#define SOL_EXT
File extension for solution files.
Definition: filename.h:138
#define CT_N_SOLUTIONS
Number of solution boxes to deliver.
Definition: parameters.h:304
CBLAS_INLINE void TMatrixVectorProduct(unsigned int r, unsigned int c, double *A, double *b, double *o)
Product of a transposed matrix and a vector.
void NewtonSetMatrix(unsigned int i, unsigned int j, double v, TNewton *n)
Defines the matrix being used in a Newton step.
Definition: algebra.c:1157
unsigned int GetNumTermsInLinearConstraint(TLinearConstraint *lc)
Number of variables in a linear constraint.
void GetCSVariables(Tvariables *vs, TCuikSystem *cs)
Gets the cuiksystem variables.
Definition: cuiksystem.c:2550
#define CT_DUMMIFY
Dummification level.
Definition: parameters.h:339
void EvaluateCSJacobian(double *p, double ***J, TCuikSystem *cs)
Evaluates the Jacobian of the system in a given point.
Definition: cuiksystem.c:5108
void ResetEquation(Tequation *eq)
Reset equation information.
Definition: equation.c:442
void SetInitialTime(double tm, Tstatistics *t)
Sets a new initial time.
Definition: statistics.c:109
unsigned int VariableSetSize(Tvariable_set *vs)
Gets the number of elements of a variable set.
Definition: variable_set.c:449
A box.
Definition: box.h:83
void LoadListOfBoxes(FILE *f, Tlist *list)
Loads a list of boxes from a file.
Definition: box_list.c:334
double GetEquationValue(Tequation *eq)
Gets the right-hand value of the equation.
Definition: equation.c:1212
void MergeConstants(Tconstants *c1, Tconstants *c2, Tconstants *cout)
Fuses constant sets.
Definition: constants.c:42
void PostProcessBox(Tparameters *p, unsigned int c, FILE *f_out, Tlist *sol, Theap *boxes, Tbox *b, TCuikSystem *cs)
Process a box after being reduced.
Definition: cuiksystem.c:1059
Data associated with each variable in the problem.
Definition: variable.h:84
void NewSplittedBox(Tstatistics *t)
Increases the number of splitted boxes.
Definition: statistics.c:156
void InitListOfBoxes(Tlist *l)
Constructor.
Definition: box_list.c:24
unsigned int GetNumDummyVariables(Tvariables *vs)
Gets the number of dummy variables in a set.
Definition: variables.c:82
void GetLinearConstraintError(Tinterval *error, TLinearConstraint *lc)
Gets the right-hand side interval for the linear constraint.
Definition of the TSimplex type and the associated functions.
A cuiksystem, i.e., a set of variables and equations defining a position analysis problem...
Definition: cuiksystem.h:181
unsigned int GetNumSystemVariables(Tvariables *vs)
Gets the number of system variables in a set.
Definition: variables.c:90
void * GetCurrent(Titerator *i)
Gets the element pointed by the iterator.
Definition: list.c:299
#define NO_UINT
Used to denote an identifier that has not been initialized.
Definition: defines.h:435
CBLAS_INLINE void SumVectorScale(unsigned int s, double *v1, double w, double *v2, double *v)
Adds two vectors with a scale.
Definition: basic_algebra.c:86
void InitBoxFromPoint(unsigned int dim, double *p, Tbox *b)
Initializes a box from a point.
Definition: box.c:43
void AddVariable2Monomial(unsigned int fn, unsigned int varid, unsigned int p, Tmonomial *f)
Adds a power variable to the monomial.
Definition: monomial.c:171
double IntervalCenter(Tinterval *i)
Gets the interval center.
Definition: interval.c:129
unsigned int CropLinearConstraint(double epsilon, unsigned int varType, Tbox *b, Tvariables *vs, TLinearConstraint *lc)
Reduce the ranges for.
boolean IsSystemVarInSimpCS(Tparameters *p, char *v, TCuikSystem *cs)
Identifies system variables that survive in the simplified system.
Definition: cuiksystem.c:2641
boolean CircleEquation(Tequation *eq)
Identify circle equations.
Definition: equation.c:1131
#define REDUCED_BOX_WITH_SOLUTION
One of the possible results of reducing a box.
Definition: box.h:52
Tvariable * GetVariable(unsigned int n, Tvariables *vs)
Gets the information of a variable given its number in the set (i.e., its identifier).
Definition: variables.c:189
void AddCt2LinearConstraint(double ct, TLinearConstraint *lc)
Adds a constant term to the linear constraint.
void PrintCuikSystem(Tparameters *p, FILE *f, TCuikSystem *cs)
Prints a cuiksystem.
Definition: cuiksystem.c:5359
void SimplePointFromOriginal(double *o, double **s, Tmapping *m)
Gets a simple point from an original one.
Definition: csmapping.c:165
double ErrorInInequalities(Tbox *b, TCuikSystem *cs)
Maximum inequality error for a box.
Definition: cuiksystem.c:5219
void EvaluateInequalityEquations(double *v, double *r, Tequations *eqs)
Error in inequalities.
Definition: equations.c:2755
boolean IsDummyEquation(unsigned int i, Tequations *eqs)
Identify dummy equations.
Definition: equations.c:1229
void EvaluateSubSetEqualityEquations(double *v, boolean *se, double *r, Tequations *eqs)
Evaluates a subset of the equality equations in the set.
Definition: equations.c:2607
Tvariables variables
Definition: cuiksystem.h:205
boolean CSRemoveVarsWithCtRange(Tparameters *p, boolean *replaced, TLinearConstraint *lc, Tbox *borig, TCuikSystem *cs)
Removes variables with constant range.
Definition: cuiksystem.c:1286
void GetCSVariableNames(char **varNames, TCuikSystem *cs)
Gets points to the variable names.
Definition: cuiksystem.c:2555
double GetMonomialCt(Tmonomial *f)
Gets the scale factor of a monomial.
Definition: monomial.c:136
void DeleteBox(void *b)
Destructor.
Definition: box.c:1283
unsigned int GetCSTopology(Tparameters *p, unsigned int **t, TCuikSystem *cs)
Topology of the variables in the system.
Definition: cuiksystem.c:2728
void PrintBoxSubset(FILE *f, boolean *used, char **varNames, Tbox *b)
Prints a (sub-)box.
Definition: box.c:1162
boolean SimpInequalitiesHoldOnPoint(Tparameters *pr, double *p, TCuikSystem *cs)
Tests if all simplified inqualities hold for a given point.
Definition: cuiksystem.c:5268
unsigned int simp_nee
Definition: cuiksystem.h:230
boolean IsInside(double p, double tol, Tinterval *i)
Checks if a value is inside an interval.
Definition: interval.c:348
boolean SimplexColEmpty(unsigned int ncol, TSimplex *s)
Checks if a simplex column is empty.
Definition: simplex_clp.c:159
void SimpleFromOriginal(Tbox *o, Tbox *s, Tmapping *m)
Gets a simple box from an original one.
Definition: csmapping.c:143
void CopyJacobian(TJacobian *j_dst, TJacobian *j_src)
Constructor.
Definition: jacobian.c:34
unsigned int nvariables
Definition: cuiksystem.h:208
void DeleteVariables(Tvariables *vs)
Destructor.
Definition: variables.c:354
double randomInInterval(Tinterval *t)
Returns a random double in the given interval.
Definition: random.c:67
void PrintMonomials(FILE *f, char **varNames, Tequation *eq)
Prints an equation as a set if monomials.
Definition: equation.c:1803
The Jacobian of a set of equations.
Definition: jacobian.h:23
boolean ScalarEquations(Tequations *eqs)
Identifies scalar systems.
Definition: equations.c:1204
Tinterval * GetBoxIntervals(Tbox *b)
Returns a pointer to the array of intervals defining the box.
Definition: box.c:284
#define CT_MAX_NEWTON_ITERATIONS
Maximum number of iterations in the Newton-Raphson function.
Definition: parameters.h:311
void AddLinearConstraints(TLinearConstraint *lc1, TLinearConstraint *lc)
Adds one linear constraint to another.
unsigned int ExtractMinElement(void *e, Theap *heap)
Extracts and removes the minimal element of a heap.
Definition: heap.c:356
unsigned int GetNSolutionBoxes(Tstatistics *t)
Gets the number of solution boxes.
Definition: statistics.c:191
char * GetVariableName(Tvariable *v)
Gets the variable name.
Definition: variable.c:63
unsigned int simp_nvariables
Definition: cuiksystem.h:229
unsigned int orig_nvariables
Definition: cuiksystem.h:246
double GetParameter(unsigned int n, Tparameters *p)
Gets the value for a particular parameter.
Definition: parameters.c:93
A generic binary heap.
Definition: heap.h:105
#define MAX_TERMS_SIMP
Maximum number of terms to be used in the simplifications.
Definition: equation.h:31
void IntervalProduct(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Product of two intervals.
Definition: interval.c:389
Tequations simp_equations
Definition: cuiksystem.h:225
#define CT_STATE_PERIOD
Period between two consecutive savings of the state.
Definition: parameters.h:296
void IntervalPow(Tinterval *i, unsigned int p, Tinterval *i_out)
Power of a given interval by a integer power factor.
Definition: interval.c:494
boolean SphereEquation(Tequation *eq)
Identify sphere equations.
Definition: equation.c:1145
void NewInterval(double lower, double upper, Tinterval *i)
Constructor.
Definition: interval.c:47
void VerifyCuikSystem(Tparameters *p, TCuikSystem *cs)
Checks the consistency of the cuiksystem.
Definition: cuiksystem.c:2206
void EvaluateSimpCSEquations(Tparameters *pr, double *p, double *r, TCuikSystem *cs)
Evaluates the simplified equation set on a point.
Definition: cuiksystem.c:5092
unsigned int simp_nequations
Definition: cuiksystem.h:228
void CopyMapping(Tmapping *m_dst, Tmapping *m_src)
Copy constructor.
Definition: csmapping.c:64
#define INF
Infinite.
Definition: defines.h:70
double GetLinearConstraintCoefficient(unsigned int i, TLinearConstraint *lc)
Gets the a particular linear constraint coefficient.
void AddCt2Monomial(double k, Tmonomial *f)
Scales a monomial.
Definition: monomial.c:158
void GetOriginalVarRelation(unsigned int nvo, TLinearConstraint *lc, Tmapping *m)
Gets the relation for a variable in the original set with the variables in the simple set...
Definition: csmapping.c:112
Tconstants constants
Definition: cuiksystem.h:182
List iterator.
Definition: list.h:61
void SetCSSearchMode(unsigned int sm, Tequation *eqMin, TCuikSystem *cs)
Sets the search mode for the cuiksystem.
Definition: cuiksystem.c:2433
#define REDUCED_BOX
One of the possible results of reducing a box.
Definition: box.h:38
double EvaluateCSCost(Tparameters *p, boolean simp, double *s, void *cs)
Evalutes the equation to minimize in a given point.
Definition: cuiksystem.c:5162
boolean CmpBoxesEquation(void *b1, void *b2, void *cs)
Determines which box to explore first in minimization mode.
Definition: cuiksystem.c:2428
void AddFirstElement(void *Info, Tlist *list)
Adds an element at the head of the list.
Definition: list.c:196
boolean CmpBoxDepthFirst(void *b1, void *b2, void *userData)
Determines which box to explore first in depth first mode.
Definition: box.c:1129
Tinterval * GetVariableInterval(Tvariable *v)
Gets the range of valid values for the variable.
Definition: variable.c:73
void DeleteEquations(Tequations *eqs)
Destructor.
Definition: equations.c:2862
void DeleteConstants(Tconstants *cts)
Destructor.
Definition: constants.c:137
unsigned int GetCSVariableID(char *name, TCuikSystem *cs)
Gets the numerical identifier of a variable given its name.
Definition: cuiksystem.c:2607
unsigned int * varType
Definition: cuiksystem.h:213
void PrintEquations(FILE *f, char **varNames, Tequations *eqs)
Prints a set of equations.
Definition: equations.c:2806
Definition of basic randomization functions.
double GetElapsedTime(Tstatistics *t)
Elapsed time.
Definition: statistics.c:92
void PrintBox(FILE *f, Tbox *b)
Prints a box.
Definition: box.c:1142
unsigned int GetCSNumNonDummyVariables(TCuikSystem *cs)
Gets the number of non-dummy variables already in the cuiksystem.
Definition: cuiksystem.c:2579
void NewBoxProcessed(Tstatistics *t)
Increases the number of processed boxes.
Definition: statistics.c:126
void NewtonSetRH(unsigned int i, double v, TNewton *n)
Defines the vector being used in a Newton step.
Definition: algebra.c:1162
void InitHeapOfBoxes(boolean(*LessThan)(void *, void *, void *), void *userData, Theap *h)
Constructor.
Definition: box_heap.c:21
unsigned int GetCSVarTopology(unsigned int vID, TCuikSystem *cs)
Determines the topology of a given variable.
Definition: cuiksystem.c:2672
boolean * orig_systemVar
Definition: cuiksystem.h:247
char * VariableName(unsigned int i, Tvariables *vs)
Gets the name for a particular variable.
Definition: variables.c:242
void Heap2List(Tlist *l, Theap *h)
Converts a heap of boxes into a list.
Definition: box_heap.c:82
boolean SimplifyCuikSystem(Tparameters *p, TCuikSystem *cs)
Simplifies a cuiksystem.
Definition: cuiksystem.c:1541
Defines a interval.
Definition: interval.h:33
boolean * notDummyVar
Definition: cuiksystem.h:211
void NewSolutionBox(boolean validated, double v, double d, Tstatistics *t)
Increases the number of solution boxes.
Definition: statistics.c:134
void ChangeParameter(unsigned int n, double v, Tparameters *p)
Sets the value for a particular parameter.
Definition: parameters.c:164
unsigned int RegenerateOriginalPoint(Tparameters *p, double *s, double **o, TCuikSystem *cs)
Generates an original point from a simplified point.
Definition: cuiksystem.c:4978
unsigned int GetVariablesTopology(unsigned int **t, Tvariables *vs)
Gets the topology for the variables in the set.
Definition: variables.c:222
void AddJacobianEquationsInt(Tparameters *p, boolean *selectedVars, TJacobian *J, TCuikSystem *cs)
Adds linear combination of the Jacobian to the system.
Definition: cuiksystem.c:2742
boolean IsInSimple(unsigned int v, Tmapping *m)
Identify original variables also present in the simple system.
Definition: csmapping.c:130
void InitMonomial(Tmonomial *f)
Constructor.
Definition: monomial.c:17
double IntervalSize(Tinterval *i)
Gets the uppser limit.
Definition: interval.c:96
void RewriteEquation2Orig(Tmapping *map, Tequation *eqOut, Tequation *eq)
Applies the un-simplification mapping to an equation.
Definition: equation.c:321
void GetSimpCSJacobian(Tparameters *p, TJacobian *J, TCuikSystem *cs)
Defines the Jacobian of a simplified CuikSystem.
Definition: cuiksystem.c:2734
unsigned int GetCSNumVariables(TCuikSystem *cs)
Gets the number of variables already in the cuiksystem.
Definition: cuiksystem.c:2565
void DeleteStatistics(Tstatistics *t)
Destructor.
Definition: statistics.c:274
void GetCSEquation(unsigned int n, Tequation *eq, TCuikSystem *cs)
Gets the an equation from a cuiksystem.
Definition: cuiksystem.c:2688
void AccumulateEquations(Tequation *eqn, double ct, Tequation *eq)
Adds a scaled equation to another equation.
Definition: equation.c:366
unsigned int GetNumMonomials(Tequation *eq)
Number of monomials in an equation.
Definition: equation.c:1703
boolean UsedVarInEquations(unsigned int nv, Tequations *eqs)
Checks if a variable is used in the set of equations.
Definition: equations.c:847
double ErrorInSimpInequalitiesOnPoint(Tparameters *pr, double *p, TCuikSystem *cs)
Computes the maximum error in all the simplified inqualities for a given point.
Definition: cuiksystem.c:5291
void DummifyCuikSystem(Tparameters *p, TCuikSystem *cs)
Apply the selected dummification level to a cuiksystem.
Definition: cuiksystem.c:695
#define DIVERGED
One of the possible outputs of the Newton iteration.
Definition: cuiksystem.h:111
void MPI_SolveCuikSystem(Tparameters *p, boolean restart, char *fstate, Tbox *searchSpace, FILE *f_out, TCuikSystem *cs)
Determines the solution set for a cuiksystem. Main scheduler.
Definition: cuiksystem.c:4369
#define DUMMY_VAR
One of the possible type of variables.
Definition: variable.h:53
#define LINKS_EXT
File extension for files with samples represented by the link poses.
Definition: filename.h:181
double GetBoxVolume(boolean *used, Tbox *b)
Computes the volume of the box.
Definition: box.c:980
void SimplexDelete(TSimplex *s)
Destructor.
Definition: simplex_clp.c:367
boolean Advance(Titerator *i)
Moves an iterator to the next position of its associated list.
Definition: list.c:373
double * GetNewtonMatrixBuffer(TNewton *n)
Buffer to store the Newton matrix.
Definition: algebra.c:1147
void NewRBError(Tstatistics *t)
Increases the number of errors when reducing a boxe.
Definition: statistics.c:165
unsigned int nequations
Definition: cuiksystem.h:207
unsigned int GetEquationType(Tequation *eq)
Gets the equation type.
Definition: equation.c:1207
boolean GaussianElimination(Tequations *eqs)
Perform Gaussian elimination on the set of equations.
Definition: equations.c:993
unsigned int GenerateSimplifiedPoint(Tparameters *p, double *o, double **s, TCuikSystem *cs)
Generates a simplified point.
Definition: cuiksystem.c:4992
void InitNewton(unsigned int nr, unsigned int nc, TNewton *n)
Defines a Newton structure.
void NewMaxLevel(unsigned int m, Tstatistics *t)
Sets a new maximum level.
Definition: statistics.c:117
void BoxFromVariables(Tbox *b, Tvariables *vs)
Creates a box from the ranges of a set of variables.
Definition: variables.c:283
void SaveListOfBoxes(FILE *f, Tlist *list)
Saves a list of boxes.
Definition: box_list.c:316
Tvariable_set * GetEquationVariables(Tequation *eq)
Gets the set of variables equation used in the equation.
Definition: equation.c:1241
#define CT_SIMPLIFICATION_LEVEL
Simplification level.
Definition: parameters.h:378
unsigned int GetEquationOrder(Tequation *eq)
Gets the equation order.
Definition: equation.c:1236
void DeleteMonomial(Tmonomial *f)
Destructor.
Definition: monomial.c:289
boolean LinearEquation(Tequation *eq)
Identify linear equations.
Definition: equation.c:1099
unsigned int CuikGradientInBox(Tparameters *p, Tbox *bIn, double *sol, Tbox *b_sol, TCuikSystem *cs)
Applies gradient descent to a set of equations.
Definition: cuiksystem.c:3961
Tequation simp_eqMin
Definition: cuiksystem.h:235
void GenerateSimpInitialBox(Tparameters *p, Tbox *box, TCuikSystem *cs)
Gives the search space in the form of a box for the simplified system.
Definition: cuiksystem.c:4854
boolean UsedVarInNonDummyEquations(unsigned int nv, Tequations *eqs)
Checks if a variable is used in the set of equations.
Definition: equations.c:822
unsigned int GetEquationCmp(Tequation *eq)
Gets the type of relational operator of the equation.
Definition: equation.c:1202
void IntervalOffset(Tinterval *i, double offset, Tinterval *i_out)
Interval offset.
Definition: interval.c:627
void AddList2Heap(Tlist *l, Theap *h)
Adds a list of boxes into a heap.
Definition: box_heap.c:97
double ErrorInSolution(Tbox *b, TCuikSystem *cs)
Maximum error for a box.
Definition: cuiksystem.c:5180
boolean ReplaceVariableInEquations(double epsilon, unsigned int nv, TLinearConstraint *lc, Tequations *eqs)
Replaces a variable with a linear expression.
Definition: equations.c:912
void PrintVariables(FILE *f, Tvariables *vs)
Prints a set of variables to an stream.
Definition: variables.c:318
void LoadCSState(char *fname, Tlist *lb, TCuikSystem *cs)
Retrives the internal the cuik solver state information from a file.
Definition: cuiksystem.c:2134
boolean SaddleEquation(Tequation *eq)
Identify scaled saddle equations.
Definition: equation.c:1159
boolean SampleCuikSystemInBox(Tparameters *p, char *fname, Tlist *sb, unsigned int nsamples, unsigned int ntries, unsigned int ndof, Tbox *init_box, TCuikSystem *cs)
Generates samples for a cuiksystem in given box.
Definition: cuiksystem.c:3007