[CONTACT]

[ABOUT]

[POLICY]

structures satisfying finite This mo

Found at: ftp.icm.edu.pl:70/packages/netlib/magic/tr.c

/**** Transferred Refutation procedures for generating
      structures satisfying finite constraints.  This 
      module is independent of the specific structures 
      being generated.
           
      The calling program must contain a header:
           
             #define V_LENGTH mmm
             #define SZ       nnn
             #define DONE     xxxx
       
       The constants V_LENGTH and SZ are used to set
       bounds on various arrays.  V_LENGTH is the number
       of variables to be assigned values, and SZ is the
       maximum number of values possible for a variable.
       A call to transref() passes a parameter of type 
       int representing the length of the actual vectors
       being searched for.  This must be less than V_LENGTH.
       The other parameters are pointers to case-relative 
       functions somewhere outside transref().  The 
       function (*Good)(vec) has to convert the vector vec
       of (unsigned) integers into whatever data structures 
       are testable, call some appropriate test routines 
       and fill in the vector as a boolean array recording 
       a refutation if one was discovered.  The function 
       (*setposs)(vec) must trim vec, now the vector of 
       possible-value sets, by removing unwanted values.  
       It must not add any possible values to it.  If 
       end-of-search status is raised (e.g. because time 
       runs out) this may be recorded by setting the 
       external variable DONE to a nonzero value.  DONE is
       defined in the header as some global variable such
       as  global_memory->problem_done.


*************************************************************
************************************************************/

#define STAK_MAX 7000
#define CUT_MAX  100
#define TOOBIG 350
#define MAXREF   (fixt/3)+2

#define REF struct ref

REF { int force, xyz; 
      REF *up, *back, *forth, *next, *last;
    } *dummy, *yonder;

nt oldvect[V_LENGTH],      /* The Way We Were         */
    vpos[V_LENGTH],         /* Vector positions        */
    skip,                   /* Bottom of refutation    */
    ts,                     /* Cell totally suspended  */
    recs,                   /* Amount of stack used    */
    susguy,                 /* The suspended cell      */
    cells,                  /* Actual vector length    */
    maxval,                 /* Max. poss. values/cell  */
	poss_tot,               /* Not "toss_pot"!         */
    fixt,                   /* Active vector length    */
    notop,                  /* Topless refutation      */
    novect,                 /* No remaining good guy   */
    newcut,                 /* Cut made on this pass   */
    rpt,                    /* Repeating after cut     */
    cutptr;                 /* Depth of cut-and-guess  */

unsigned poss[V_LENGTH],    /* Poss. values in order   */
         val[V_LENGTH],     /* Actual values of cells  */
         used[V_LENGTH],    /* Latest refutation       */
         comvec[V_LENGTH],  /* communication vector    */
         cuts[CUT_MAX][3];  /* Cut-and-guess divisions */

REF Dum, Yon,               /* The actual dummies      */
    stak[STAK_MAX],         /* A chunk of memory       */
     inx[V_LENGTH][SZ];     /* Index to the stack      */


/************************************************************
************************************************************/

transref( length, Test, Setposs )  
          int length, (*Test)(), (*Setposs)();
{
   tr_initial(length);
   while ( prepared( Setposs ) )
   if ( poss_tot > TOOBIG ) cut_and_guess();
   else search( fixt-1, Test );
}


/************************************************************
************************************************************/

                          /*** Generate all vectors on 
                               the subspace up to x that
                               satisfy function Test     ***/
{ 
   int i;
   
   if ( x < 0 )                       /** Vector complete **/
   {
      for ( i = 0; i < cells; i++ ) comvec[vpos[i]] = val[i];
      if ( !(*Test)(comvec) ) addref();
      return(0);
   }
   
   for ( val[x] = rpt? oldvect[x]: 0; 
         val[x] <= maxval;  val[x]++ )
   if ( poss[x] & ( 1 << val[x] ))
   {
      invalue( x );
      if ( !ts ) search( x-1, Test );
      if ( DONE ) novect = 1;
      if ( ts && !novect ) totsus();
      if ( novect ) break;
      outvalue( x );
      if ( x < skip ) break;
   }
   val[x] = 0;
   if ( x == fixt-1 ) novect = 1;
}



/***********************************************************/

nvalue(x)  int x;
                          /*** Insert val[x] in cell x.
                               Transfer all active
                               refutations downward.     ***/
{ register REF *ptr,*pd;
  
  ts = 0; susguy = 0;  skip = -1;
  if ( !x || val[x] > oldvect[x] ) rpt = 0;
  
  for ( ptr = inx[x][val[x]].next; 
        ptr!=dummy; ptr = ptr->next )
  { 
     pd = ptr->forth;
     if (( pd->force += ptr->force ) == ptr->force ) 
     { 
        pd->back = ptr;
        if ( pd->forth == dummy )
        { 
           if ( !(poss[pd->xyz/SZ] &= ~(1 << (pd->xyz%SZ)) ))
           { 
              ts = 1; 
              if ( pd->xyz/SZ > susguy ) susguy = pd->xyz/SZ;
           }
        }
        else
        { 
           pd->last = (*inx)+(pd->xyz);
           pd->next = pd->last->next;
           pd->last->next->last = pd;
           pd->last->next = pd;
        }
     }
  }
}



/***********************************************************/

outvalue(x)  int x;       /*** Opposite of invalue: take 
                               value out, undo transfers ***/
{ register REF *ptr,*pd;
  
  ptr = &inx[x][val[x]];
  if ( ptr->back == yonder ) 
  { 
     ptr->force = 0;
     poss[x] |= 1 << val[x];
  }
  while ( ptr->next != dummy )
  { 
     ptr = ptr->next;
     pd = ptr->forth;
     if ( !( pd->force -= ptr->force ))
     { 
        pd->back = dummy;
        if ( pd->forth == dummy )
        poss[pd->xyz/SZ] |= 1 << (pd->xyz%SZ);
        else
        { 
           pd->last->next = pd->next;
           if ( pd->next != dummy ) pd->next->last = pd->last;
        }
     }
     if ( ptr->back == yonder )
     { 
        ptr->force = 0;
        ptr->last->next = ptr->next;
        if ( ptr->next != dummy ) ptr->next->last = ptr->last;
     }
  }
} 



/***********************************************************/

                 Remove the top if necessary. Return its 
                 cardinality.                            ***/
{ register int i,j;
  int k;

  k = notop = 0;
  for ( i=0; i<fixt; i++ ) if ( used[i] ) 
  {
     k++;
     if ( skip < 0 ) skip = i;
  }
  if ( !k ) novect = 1;
  else
  { 
     for ( i--; i>skip && used[i]; i-- )
     if ( i < fixt-1 )
     { 
        used[i+1] = 0;  notop = 1;
        k--;
     }
     j = i+1;
     while ( k > MAXREF )
     { 
        if ( used[--i] )
        { 
           used[j] = 0;
           notop = 1;  k--;  j = i;
        }
     }
     if ( notop && k==1 ) used[skip] = k = 0;
  }
  return(k);
}



/***********************************************************/

addref()
                    /*** Incorporate the refutation in the 
                         appropriate active lists.       ***/
{ register REF *here;
  register int i;
  int k,trunk;
  REF *there, *newguy();
  
  if ( skip < 0 )
  for ( i = 0; i < fixt; i++ ) used[i] = comvec[vpos[i]];
  k = setref();
  if (!k) return(0);
  trunk = 1;  i = skip;  
  here = &inx[i][val[i]];  here->force = 1;  
  if ( !(poss[i] &= ~(1 << val[i])) ) { ts = 1; susguy = i; }
  
  for (k-- ; k; k--)
  { 
     for ( used[i] = 0; !used[i]; i++ ) ;
     there = here;
     if (trunk)
     { 
        for ( here = &inx[i][val[i]];
              here->forth != there && here->up != dummy;
              here = here->up ) ;
        if (here->forth != there) trunk = 0;
     }
     if ( !trunk ) ( here = newguy(i) )->forth = there; 
     here->force++;
     if ( here->xyz > there->back->xyz ) there->back = here;
     if ( here->force == 1 )
     { 
        here->last = &inx[i][val[i]];
        if (( here->next = here->last->next ) != dummy )
        here->next->last = here;
        here->last->next = here;
     }
  }
  
  used[i] = 0;
  here->back = notop? yonder: here;
  if ( recs >= STAK_MAX-MAXREF ) cut_and_guess();
}



/***********************************************************/

REF *newguy(x) int x;    /*** Get next record ***/
{ REF *ng;

  ng = stak+recs++;
  ng->force = 0;
  ng->back = dummy;
  ng->xyz = (x*SZ)+val[x];
  ng->up = ((*inx)+(ng->xyz))->up;
  ((*inx)+(ng->xyz))->up = ng;
  return(ng);
}



/***********************************************************/

totsus()                          /*** Action on detection 
                                   of total suspension ***/
{ 
  while (ts)
  { 
     ts = 0;
     getsus();
     if ( !novect ) addref();
     if ( novect )  return(0);
  }
}



/***********************************************************/

                                    find a subset doing the 
                                    suspending.  If no top 
                                    fill used[] ***/
{ register REF *ptr;
  register int i;
  int k;
  
  k = fixt;
  for ( i = 0; i <= maxval; i++ )
  { 
     for (ptr = &inx[susguy][i];
          ptr->back != ptr && ptr->back != yonder;
          ptr = ptr->back)
     used[ptr->back->xyz/SZ] = 1;
     if (ptr->back == yonder && k > ptr->xyz/SZ )
     for ( k--; k > ptr->xyz/SZ; k-- ) used[k] = 1;
  }
  for ( skip = susguy+1; skip < fixt; skip++ )
  if ( used[skip] ) return(0);
  novect = 1;
}



/***********************************************************/

cut_and_guess()   /*** Fix the present value in the most 
                       significant cell.  Stack the cut. ***/
{ int i;

  if ( cutptr++ == CUT_MAX ) skipout("Cut stack overflow");
  newcut = rpt = 1;
  for ( i = 0; i < cells; i++ ) oldvect[i] = val[i];
  cuts[cutptr][0] = vpos[fixt-1];
  cuts[cutptr][1] = 1 << val[fixt-1];
  cuts[cutptr][2] = poss[fixt-1];
  for ( i = 0; i <= val[fixt-1]; i++ )
  cuts[cutptr][2] &= ~(1 << i);
  novect = 1;
}



/***********************************************************/

                  through the cut stack to recover the old 
                  search space and prime the new.       ***/
{ int i;

  if ( !newcut )
  { 
     while ( cutptr && (!cuts[cutptr][2]) ) cutptr--;
     if ( !cutptr ) novect = 1; else
     {
        cuts[cutptr][1] = cuts[cutptr][2];
        cuts[cutptr][2] = 0;
     }
     rpt = 0;
  }
  newcut = 0;
  for ( i = 1; i <= cutptr; i++ )
  comvec[cuts[i][0]] = cuts[i][1];
}




/***********************************************************/

                                      /*** Poss initialised ***/
{ int i,j,k;
  
  if (( novect && !cutptr ) || DONE ) return(0);
  novect = 0;
  for ( i = 0; i < cells; i++ ) 
  comvec[i] = (1 << SZ) - 1;
  for ( i = cells; i < V_LENGTH; i++ ) comvec[i] = 0;
  if ( cutptr ) do_cuts();
  if ( novect ) return(0);
  (*Setposs)(comvec);
  maxval = 0;  poss_tot = 0;
  for ( i = 0; i < cells; i++ ) 
  {
     if ( !comvec[i] ) 
     {
        novect = 1;
        return( prepared(Setposs) );
     }
	 for ( j = 0; j < SZ; j++ ) if ( comvec[i] & (1 << j) )
	 {
		poss_tot++;
        if ( j > maxval ) maxval = j;
	 }
  }
  re_order();
  setinx();
  if ( rpt ) 
  { 
     if ( !set_old() ) 
     {
        novect = 1;
        return( prepared(Setposs) );
     }
  }
  for ( i = 0; i < cells; i++ )
  for ( val[i] = 0; !(poss[i] & (1 << val[i])); val[i]++ ) ;
  skip = -1; recs = 0;
  if ( !fixt ) novect = 1;
  return(1);
}



/**********************************************************/

{ int i,j,k, newpos[V_LENGTH], newold[V_LENGTH];
  
  k = 0;  fixt = cells;
  for ( i = 0; i < cells; i++ )
  {
     for ( j = 0; !(comvec[i] & (1 << j)); j++ ) ;
     if ( comvec[i] == (1 << j) ) newpos[--fixt] = i;
     else newpos[k++] = i;
  }
  for ( i = 0; i < cells; i++ )
  {
     for ( j =0 ; vpos[j] != newpos[i]; j++ ) ;
     newold[i] = oldvect[j];
  }
  for ( i = 0; i < cells; i++ ) 
  {
     vpos[i] = newpos[i];
     poss[i] = comvec[vpos[i]];
     oldvect[i] = newold[i];
  }
}


/***********************************************************/

                               lists starting from inx   ***/
{ 
  REF *p;
  int i,j;

  for ( i = 0; i < cells; i++ )
  for ( j = 0; j < SZ; j++ )
  {
     p = &inx[i][j];
     p->xyz = (SZ*i)+j;
     p->force = ( poss[i] & (1 << j) )? 0: 1;
     p->up = p->forth = p->last = p->next = dummy;
     p->back = p->force? p: dummy;
  }
}



/*********************************************************/

                                  next possible vector ***/
{
  int i,j,k;
  
  for ( k = cells-1; k >= 0; k-- )
  {
     for ( i = 0; vpos[i] != k; i++ ) ;
     if ( !(poss[i] & (1 << oldvect[i])) ) break;
  }
  if ( k < 0 ) return(1);
  for ( j = 0; j < cells; j++ )
  if ( vpos[j] < k ) oldvect[j] = 0;
  while ( k < cells )
  {
     for ( i = 0; vpos[i] != k; i++ ) ;
     for ( j = oldvect[i]+1; j <= maxval; j++ )
     if ( poss[i] & (1 << j) )
     {
        oldvect[i] = j; return(1);
     }
     oldvect[i] = 0;
    k++; 
  }
  return(0);
}


/**********************************************************
**********************************************************/

tr_initial(length)  int length;  /*** Set up dummy, yonder, 
                                 cells, maxval, vpos, etc. ***/
{ 
  int i;
  
  if ( !(cells = length) ) 
  skipout("Attempt to search null space");
  Dum.force = Dum.xyz = 0;
  dummy = Dum.up = Dum.forth = Dum.back 
        = Dum.next = Dum.last = &Dum;
  Yon.force = Yon.xyz = 0;
  yonder = Yon.up = Yon.forth = Yon.back 
         = Yon.next = Yon.last = &Yon;
  for ( i = 0; i < cells; i++ ) vpos[i] = i;
  rpt = cutptr = newcut = 0;
  DONE = novect = 0;
}

/**********************************************************
**********************************************************/
{ 
  printf("\n\n\n Aborting on detection of an error.\n\n");
  printf(" %s.\n\n", s);
  exit(0);
}    

.


AD:

NEW PAGES:

[ODDNUGGET]

[GOPHER]