Esempio n. 1
0
static void backtrack(int *out, int *rowsum, int *colsum, int fill,
		      int nr, int nc, int *rfill, int *cfill, int *ind)
{
    int tmp, i, j, k, ir, ic;
    int izero = nr * nc - 1, ielig = nr * nc - 1, npick = 0, oldpick = 0,
	ndrop = 1, dropouts[BACKSTEP], idrop = 0, lastpick = 0;

    /* initialize */
    for(i = 0; i < nr * nc; i++)
	ind[i] = i;
    memset(rfill, 0, nr * sizeof(int));
    memset(cfill, 0, nc * sizeof(int));

    /* check for empty rows/columns and move their indices from eligible */

    for (ir=0; ir < nr; ir++)
	if (rowsum[ir] <= 0)
	    for (i = ielig; i > EMPTY; i--)
		if (ind[i] % nr == ir) {
		    SWAP(ind[i], ind[ielig]);
		    ielig--;
		}
    for (ic=0; ic < nc; ic++)
	if (colsum[ic] <= 0)
	    for (i = ielig; i > EMPTY; i--)
		if (ind[i] / nr == ic) {
		    SWAP(ind[i], ind[ielig]);
		    ielig--;
		}
    
    /* Start working */
    while(npick < fill) { /* outermost loop (placeholder) */
	/* fill */
#if LOUD
	Rprintf("\nFILL ");
#endif
	while(ielig > EMPTY) {
	    i = IRAND(ielig); /* eligible: always succeed */
#if LOUD
	    Rprintf("pick %d ", i);
#endif
	    ir = ind[i] % nr; /* row */
	    ic = ind[i] / nr; /* column */
	    npick++;
	    SWAP(ind[i], ind[ielig]); /* move after izero */
	    if (ielig < izero) {
		SWAP(ind[ielig], ind[izero]);
	    }
	    ielig--;
	    izero--;
	    /* update fills and move from eligible if marginal sum reached */
	    if (++rfill[ir] == rowsum[ir])
		for(i = ielig; i > EMPTY; i--)
		    if (ind[i] % nr == ir) {
#if LOUD
			Rprintf("ban %d ", i);
#endif
			SWAP(ind[i], ind[ielig]);
			ielig--;
		    }
	    if (++cfill[ic] == colsum[ic])
		for (i = ielig; i > EMPTY; i--)
		    if (ind[i] / nr == ic) {
#if LOUD
			Rprintf("ban %d ", i);
#endif
			SWAP(ind[i], ind[ielig]);
			ielig--;
		    }
	}
	/* get out */
#if LOUD
	if (npick != oldpick) Rprintf("\n*** PICKED %d ", npick);
#endif
	R_CheckUserInterrupt();
	if (npick == fill)
	    break;
	
#if RESET
	
	/* if we did worse than previously, undo: remove picked items
	 * and put back the ones removed as dropouts */

	if (npick < oldpick) {
#if LOUD
	    Rprintf("\nRESET ");
#endif
	    /* first items after izero were added in the last cycle --
	     * these should be removed except for the originally
	     * dropped items (dropouts) that should be kept */

	    lastpick = izero + ndrop - oldpick + npick;
	    for (i = izero+1; i <= lastpick; i++) {
		k = imatch(ind[i], dropouts, idrop+1);
		if (k == EMPTY)  { /* remove pick: not a dropout */
#if LOUD
		    Rprintf("drop %d ", i);
#endif
		    rfill[ind[i] % nr]--;
		    cfill[ind[i] / nr]--;
		    npick--;
		    izero++;
		    if (izero < i) {
			SWAP(ind[i], ind[izero]);
		    }
		} else { /* remove from dropouts */
#if LOUD
		    Rprintf("keep %d ", i);
#endif
		    dropouts[k] = dropouts[idrop--];
		}
	    }
	    
	    /* The dropouts are among first items of ind: search these and
	     * add back to picked. */

	    i = EMPTY;
	    while(idrop > EMPTY) {
		k = imatch(ind[++i], dropouts, idrop+1);
		if (k != EMPTY) { /* pick back this item */
#if LOUD
		    Rprintf("pick %d ", i);
#endif
		    rfill[ind[i] % nr]++;
		    cfill[ind[i] / nr]++;
		    SWAP(ind[i], ind[izero]);
		    izero--;
		    npick++;
		    dropouts[k] = dropouts[idrop--];
		}
	    }
	}

#endif /* RESET */
	
        /* backtrack: remove picked items and update marginal totals
	 * and see if any items become eligible. If 'npick' did not
	 * improve from the best 'oldpick', increase 'ndrop' up to
	 * BACKSTEP, and reset 'ndrop' to 1 if 'npick' improved.  */

	if (oldpick < npick) {
	    ndrop = 1;
	    oldpick = npick;
	} else if (ndrop < BACKSTEP && ndrop < npick) {
	    ndrop++;
	}
#if LOUD
	Rprintf("\nBACKTRACK %d: ", ndrop);
#endif
	for (j = 0, idrop = EMPTY; j < ndrop; j++) {
	    i = IRAND(npick-1) + izero + 1;
#if LOUD
	    Rprintf("%d ", i);
#endif
	    dropouts[++idrop] = ind[i]; /* save removed */
	    rfill[ind[i] % nr]--;
	    cfill[ind[i] / nr]--;
	    npick--;
	    ielig++;
	    izero++;
	    SWAP(ind[i], ind[izero]);
	    SWAP(ind[izero], ind[ielig]); /* if elig is EMPTY: move to ind[0] */
	}
	/* see what can be moved to eligible */
	for (i = izero; i > ielig; i--) {
	    ir = ind[i] % nr;
	    ic = ind[i] / nr;
	    if (rfill[ir] < rowsum[ir] && cfill[ic] < colsum[ic]) {
#if LOUD
		Rprintf("free %d ", i);
#endif
		ielig++;
		SWAP(ind[i], ind[ielig]);
	    }
	}
    }

    /* output */
    memset(out, 0, nr * nc * sizeof(int));
    /* put 1's in their places */
    for (i = izero+1; i < nr*nc; i++)
	out[ind[i]] = 1;
}
Esempio n. 2
0
 inline static dt::boolean call(const dt::istring &pattern, const dt::istring &haystack) {
   return imatch(pattern, haystack);
 }