/*****************************************************************************
 *
 * FILE : stratex.c - library of default logic tasks supported by the program
 *		      for STRATIFIED processing of queries
 *
 * programmer - Pawel Cholewinski
 *
 * date 06/27/94
 * modified 19 Apr 1999 by Neil Moore <neil@cs.uky.edu>
 * modified 20 Aug 1999 by Neil Moore <neil@cs.uky.edu>
 * modified  5 Sep 1999 by Neil Moore <neil@cs.uky.edu>
 *
 * Part of sderes.  See COPYRIGHT for copyright information.
 *
 *****************************************************************************/

#include "proto.h"
#include "default.h"
#include "token.h"
#include "global.h"

int ktime;

int interval_coincide(int[], int[], int, int);
int stratum_extension(int stratum_k, int offset, int stratum_from,
		      int stratum_to);
int next_stratum_extension(int stratum_from, int stratum_to);
int next_stratum_Bomega(int stratum_from, int stratum_to);


int stratified_extnsns(int loop)
{
	int i, resp;
	
	resp = build_atomtable(NULL);
	if (resp<0) {
		if(verbosity > 0)
			fprintf(stderr, "Inconsistent theory.");
		if(verbosity > -1)
			printf("Extension 1: Cn( { 0 } )\n\n");
		return -1;
	}
	else if (resp>0) {
		if(verbosity > 0)
			fprintf(stderr, "Not disjunction-free input.\n");
		return -1;
	}
	
	while (loop--) {
		for (i=0 ; i<dno ; i++)
			GenDef[i] = ad[i] = Reduct[i] = 0;
		n_extnsns = 0;
		ktime = 0;
		resp = stratum_extension(0,0,0,stratum[0]);
		if (loop)
			clean_atomtable();
	}
	return resp;
}


int stratum_extension(int stratum_k, int offset, int stratum_from,
		      int stratum_to)
{
   int nxst, more=3, answer=0;
   int cctx=1, vartab[64], valtab[64];

   nxst = stratum_k+1;
   ktime++;
   if ((offset==stratum_from) || GenDef[offset-1]) {
	n_candidates++;
        answer = next_stratum_extension(stratum_from,stratum_to);
	if (answer < 0) return 3;
        if (answer==1) {
    	   if (nxst==n_strat) {
		 n_extnsns++;
		 emitextnsn((int)n_extnsns,GenDef);
	         if (n_extnsns==extlimit) return 1;
	      }
	      if (nxst < n_strat) more = stratum_extension
		   (nxst,stratum_to,stratum_to,stratum_to+stratum[nxst]);
	}
   }

   if (more!=3) return more;
   if (answer!=1 && offset<stratum_to) {
	GenDef[offset] = 1;
	cctx=add_facts(conc[offset],vartab,valtab);
        if (cctx>=0) {
	   more=stratum_extension
                (stratum_k,offset+1,stratum_from,stratum_to);
           if (more!=3) return more;
        }
        else {
           n_cppcalls++;
           n_candidates++;
        }
        remove_facts(vartab,valtab);
	GenDef[offset] = 0;
	more=stratum_extension(stratum_k,offset+1,stratum_from,stratum_to);
  }
  return more;
}

int next_stratum_extension(int stratum_from, int stratum_to)
{
      int i, answer;

      for (i=stratum_from; i<stratum_to ; i++) ad[i] = GenDef[i];
      for (i=stratum_from; i<stratum_to ; i++) {
	Reduct[i] = default_is_consistent(i);
	if (Reduct[i]<GenDef[i]) return -1;
      }
      for (i=stratum_from; i<stratum_to ; i++) ad[i] = 0;
      save_stratum(stratum_from,stratum_to);
      answer = next_stratum_Bomega(stratum_from,stratum_to);
      restore_stratum(stratum_from,stratum_to);
      if (answer < 0) return 0;
      if (interval_coincide(ad,GenDef,stratum_from,stratum_to)) return 1;
      else return 0;
}

int next_stratum_Bomega(int stratum_from, int stratum_to)
{
   int start, k=0;

   start = stratum_from;
   while (k>=0) {
	 k = new_monrule_first_fireable(start,stratum_to);
	 if (k<0) return start;
	 else {
	   ad[k] = 1;
	   if (GenDef[k]==0) return -1;
	   store_facts(conc[k]);
	   Reduct[k] = 0;
	    while (start<stratum_to && Reduct[start]==0) start++;
      }
   }
   return start;
}

int read_stratification(void)
{
	char znak[MAXFILENAME];
	char schar;	
	int c;
	
	strcpy(znak, def_znak);
	znak[strlen(znak)-3] = EOS;
	strcat(znak,".str");

	if(verbosity > 1)
		fprintf(stderr, "Reading stratification...");
	
	fstratif = fopen(znak, "r");
	if (fstratif==NULL) {
		n_strat = 1;
		if (verbosity > 0) {
			fprintf(stderr, "Can't open file %s\n",znak);
			fprintf(stderr, "Trivial stratification assumed.\n");
		}
		stratum[0] = dno; 
		stratum[n_strat] = -1;
		return n_strat;
	}
	
	n_strat = 0;
	while ((c=getc(fstratif))!=EOF) {
		if (isdigit(c)) {
			if ((ungetc(c,fstratif))==EOF) {
				if(verbosity > 0)
					perror("ungetc failed");
				exit(1);
			}
			fscanf(fstratif,"%d", &stratum[n_strat++]);
			if (stratum[n_strat] == 1)
				schar = ' ';
			else
				schar = 's';
		}
	}
	stratum[n_strat] = -1;
	
	if(verbosity > 1)
		fprintf(stderr, "done.\n");
	return n_strat;
}

int interval_coincide(tab1, tab2, st, lim)
   int tab1[], tab2[], st, lim;
{
   int i;

   i = st;
   while (i<lim)
        if (tab1[i] != tab2[i]) return 0;
        else i++;
   return 1;
}

