/* Torna alla pagina principale
Leggi il codice di apriori_next.c */


/* Codice C commentato */


/* Questa pagina contiene il codice C del programma. Tutti i commenti e ció che non é codice sono stati inseriti come commento, in modo da facilitare un eventuale utilizzo del codice o di parti di esso. */

/* Inizio codice */


/* File apriori_all_time.h */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <postgresql/libpq-fe.h>	/* libreria front-end di Postgresql */
#include <time.h>



/* Ecco le strutture utilizzate: */

struct transaz{		/* utilizzata per memorizzare le transazioni (struttura a coda) */
	int id;
	int *n;
	int grand;
	int freq;
	struct transaz *next;
	};

struct liv1{		/* utilizzata per i singoli elementi (item-set di grandezza 1) */
	int n;
	char spiegazione[256];
	int freq;
	struct liv1 *left;
	struct liv1 *right;
	};

struct h3{		/* utilizzata per memorizzare gli item-set */
	struct transaz *lista;
	struct h3 *next[10];
	};

struct trin{		/* utilizzata per memorizzare e ordinare per confidenza le transazioni */
	int *da;
	int *a;
	float suppda;
	float supptot;
	float conf;
	struct trin *dx;
	struct trin *cen;
	struct trin *sx;
	};

struct supp{		/* utilizzata per memorizzare e ordinare per supporto le transazioni */
	int *elem;
	float supp;
	struct supp *dx;
	struct supp *cen;
	struct supp *sx;
	};





/* Qui sotto i prototipi delle funzioni: */

struct liv1 *aggliv1(struct liv1 *liv,int l,PGconn *conn2);
void taglia(struct liv1 *liv,int livello);
void cuci(struct liv1 *r1,int a,int livello);
struct h3 *insout(int liv,int a,int fr,struct h3 *out);
void scrivi2(int a,int n);
struct transaz *alltransaz(int n,struct transaz *nex);
struct transaz *prenditr(PGresult *res,struct transaz *t);
void conta(struct transaz *t,struct h3 *n,int i,int l,int dove);
void incrementa(struct transaz *t,struct transaz *l);
struct h3 *unisci(struct h3 *z,int liv,struct h3 *r,int lcorr);
struct h3 *copia(struct h3 *r,struct transaz *a,struct transaz *b,int liv,int lcorr);
struct h3 *scriviout(struct transaz *a,int liv,int lcorr,struct h3 *o);
struct h3 *taglia2(struct h3 *r,int liv,struct h3 *o,int lcorr);
int cerca(struct transaz *f,int liv,struct h3 *o);
int cerca2(struct transaz *f2,struct h3 *o,int liv);
struct h3 *pulisci(struct h3 *t,struct h3 *r);
void pul(struct h3 *t);
struct h3 *isci(struct h3 *r);
struct h3 *suppconf(struct h3 *o);
struct supp *inss(struct transaz *l,struct supp *s);
void insc(struct transaz *l);
int **estrai(int n,int *lista,int grand,int **p,int *corr,int ora);
void cercaconf(int **p,struct transaz *l);
float cercaconf2(int *da,struct h3 *o,int liv);
struct trin *insconf(int *pk,int *a,float suppda,float supptot,float conf,struct trin *t);
struct supp *scrivisupp(FILE *file,struct supp *sup,struct liv1 *r1);
void scriviconf(FILE *file,struct trin *tri,struct liv1 *root1);
char *trovaspiegaz(int n,struct liv1 *r,char *s);
int intlen(int *s);




/* Le principali variabili: */

float limsoglia=0.01;	/* limite inferiore (soglia) del supporto (in percentuale) */
int soglia;		/* limite inferiore (soglia) del supporto (in numero intero) */
int ntransaz;		/* numero totale di transazioni */
float limconf=0.5;	/* soglia della confidenza (in percentuale) */

/* parametri di connessione: */
char conninfo[1000]="host=db.stat.unipd.it dbname=daniele user=daniele password=daniele";

/* variabili utili per la connessione al database e la lettura dei risultati */
PGconn *conn;
PGconn *conn2;
PGresult *res;

/* variabili di vario utilizzo */
int nFields,i,j,id,id2,l,last,livello;

/* puntatori alle principali strutture per l'analisi */
struct transaz *t;
struct liv1 *root1;
struct h3 *rooth3;
struct h3 *temp;


struct h3 *outh3;		/* lista stabile di output */
struct supp *sup;		/* per l'ordinamento secondo il supporto */
struct trin *tri;		/* per l'ordinamento secondo la confidenza */
FILE *file;			/* per la scrittura su file */
clock_t tp0,tp1;		/* per il calcolo del tempo utilizzato */
int discesa[10000];		/* utilizzato nella conta per il problema della sovrapposizione degli hash */






/* File apriori_all.c */



#include "apriori_all_time.h"

int main(int argc,char *argv[])
{

tp0=clock();		/* inizio a contare il tempo */

fprintf(stderr,"\n**********INIZIO ESECUZIONE**********\n");

for(i=1;i<argc;i++)				/* utilizzo degli eventuali parametri di input */
	{if(strcmp(argv[i],"-h")==0)		/* help */
		{fprintf(stderr,"\nPossibili parametri in input:\n\t\" -c 300 \" --> indica il limite minimo della confidenza (in millesimi)\n");
		 fprintf(stderr,"\t\" -s 120 \" --> indica il limite minimo del supporto (in millesimi)\n");
		 fprintf(stderr,"\t\" -p \"host=db.stat.unipd.it dbname=daniele user=daniele password=daniele\" \" --> indica i nuovi parametri di connessione al db\n\n");
		 return 1;
		}
	 if(strcmp(argv[i],"-s")==0)		/* supporto */
		{i++;
		 limsoglia=((float)atoi(argv[i])/(float)1000);
		 continue;
		}
	 if(strcmp(argv[i],"-c")==0)		/* confidenza */
	 	{i++;
	 	 limconf=((float)atoi(argv[i])/(float)1000);
	 	 continue;
		}
	 if(strcmp(argv[i],"-p")==0)		/* conninfo */
	 	{i++;
	 	 strcpy(conninfo,argv[i]);
	 	 continue;
		}
	}

fprintf(stderr,"\nlimite di confidenza: %.3f\n",limconf);
fprintf(stderr,"limite di soglia: %.3f\n",limsoglia);
fprintf(stderr,"informazioni di connessione:\n\t%s\n",conninfo);

conn=PQconnectdb(conninfo);		/* Connessione al database */
if(PQstatus(conn)!=CONNECTION_OK)
	{fprintf(stderr,"Connessione al database fallita: %s\n",PQerrorMessage(conn));
	 PQfinish(conn);
	 return 0;
	}

conn2=PQconnectdb(conninfo);		/* Seconda connessione al database */
if(PQstatus(conn2)!=CONNECTION_OK)
	{fprintf(stderr,"Connessione al database fallita: %s\n",PQerrorMessage(conn));
	 PQfinish(conn2);
	 PQfinish(conn);
	 return 0;
	}

res=PQexec(conn,"BEGIN");
if(PQresultStatus(res)!=PGRES_COMMAND_OK)
	{fprintf(stderr,"Comando BEGIN fallito: %s\n",PQerrorMessage(conn));
	 PQclear(res);
	 PQfinish(conn);
	 return 0;
	}

PQclear(res);
res=PQexec(conn,"DECLARE tr CURSOR FOR SELECT * FROM TRANSAZIONI ORDER BY ID,N");
if(PQresultStatus(res)!=PGRES_COMMAND_OK)
	{fprintf(stderr,"Comando CURSOR fallito: %s\n",PQerrorMessage(conn));
	 PQclear(res);
	 PQfinish(conn);
	 return 0;
	}

PQclear(res);
res=PQexec(conn,"FETCH ALL in tr");		/* Prendo tutte le transazioni in una sola volta */
if(PQresultStatus(res)!=PGRES_TUPLES_OK)
	{fprintf(stderr,"Comando FETCH ALL fallito: %s\n",PQerrorMessage(conn));
	 PQclear(res);
	 PQfinish(conn);
	 return 0;
	}

/* ora ho in res le transazioni (pero' nel formato della tabella) --> inizio conta a livello 1 */

if(PQntuples(res)<1)
	{fprintf(stderr,"Non ci sono transazioni da analizzare\n\n");
	 return 0;
	}


root1=NULL;
id=atoi(PQgetvalue(res,0,0));
last=atoi(PQgetvalue(res,0,1));
root1=aggliv1(root1,last,conn2);
ntransaz=1;

for(i=1;i<PQntuples(res);i++)
	{l=atoi(PQgetvalue(res,i,1));
	 id2=atoi(PQgetvalue(res,i,0));
	 if(id2!=id)			/* transazione diversa */
	 	{root1=aggliv1(root1,l,conn2);
	 	 last=l;
	 	 id=id2;
	 	 ntransaz++;
	 	 continue;
		}
					 /* stessa transazione */
	 if(l!=last)
	 	{root1=aggliv1(root1,l,conn2);
	 	 last=l;
		}
	}

/* qui ho terminato la conta a livello 1 */


livello=1;			/* livello attuale */
soglia=(int)(limsoglia*ntransaz);	/* calcolo della soglia per il supporto */

if(soglia<1)
	soglia=1;	/* voglio che almeno una volta sia presente */

fprintf(stderr,"Soglia = %d\n\n",soglia);

fprintf(stderr,"Conta a livello 1 terminata\n");

taglia(root1,livello);		/* faccio "pulizia" nella struttura root1 */
t=alltransaz(10000,NULL);
t->grand=0;

/*
ho le transazioni in *res e la lista degli elementi di livello="livello"
in struct h3 *rooth3
*/

while(rooth3!=NULL)
	{livello++;

fprintf(stderr,"Inizio conta a livello %d ",livello);
tp1=clock();
fprintf(stderr,"(Secondi trascorsi: %7.3lf)\n",(tp1-tp0)/(double)CLOCKS_PER_SEC);


	 t->freq=0;		/* utilizzo t->freq (int) per "riga a cui sono arrivato" */
	 t=prenditr(res,t);

	 while(1)		/* finche' ci sono transazioni */
	 	{if(t->grand<livello)
	 		{if(t->freq>=PQntuples(res))
			 	goto fine;
			 t=prenditr(res,t);
			 continue;	/* la transazione e' piu' piccola del livello attuale */
			}
		 conta(t,rooth3,0,0,0);
		 if(t->freq>=PQntuples(res))
		 	goto fine;
	 	 t=prenditr(res,t);
		}


fine:
	 /* ora ho la conta a livello="livello" */
	 temp=rooth3;
	 rooth3=NULL;
	 rooth3=unisci(temp,livello,rooth3,0);		/* cerco gli item-set candidati per i passi successivi */
	 rooth3=taglia2(rooth3,livello,outh3,0);	/* taglio gli item-set candidati che so non risulteranno frequenti */
	 rooth3=pulisci(temp,rooth3);		/* "pulisce" eventuali liste o transazioni vuote delle due strutture */
	}

		/* ora chiudo cursori e connessione, e dealloco la memoria occupata dai risultati */
PQclear(res);
res=PQexec(conn,"CLOSE tr");
if(PQresultStatus(res)!=PGRES_COMMAND_OK)
	{fprintf(stderr,"Comando CLOSE fallito: %s\n",PQerrorMessage(conn));
	 PQclear(res);
	 PQfinish(conn);
	 return 0;
	}

PQclear(res);
res=PQexec(conn,"END");
if(PQresultStatus(res)!=PGRES_COMMAND_OK)
	{fprintf(stderr,"Comando END fallito: %s\n",PQerrorMessage(conn));
	 PQclear(res);
	 PQfinish(conn);
	 return 0;
	}

PQclear(res);
PQfinish(conn);
PQfinish(conn2);


/*
ora ho in outh3 --> lista stabile di output organizzata a livelli e tagliata per hash,
con supporto > supp.min. (ma non so niente della confidenza)
*/

fprintf(stderr,"\nOrdinamento degli elementi per supporto e confidenza in corso ");
tp1=clock();
fprintf(stderr,"(Secondi trascorsi: %7.3lf)\n",(tp1-tp0)/(double)CLOCKS_PER_SEC);

outh3=suppconf(outh3);

/* ora ho in sup gli elementi ordinati per supporto e in tri le relazioni ordinate per confidenza */

file=fopen("supp.html","w");
if(file==NULL)
	{fprintf(stderr,"Problema nell\'apertura del file supp.html\n");
	 return 0;
	}

fprintf(file,"<html>\n<head>\n<META NAME=\"DC.Title\" CONTENT=\"Supporto\">");
fprintf(file,"\n<META NAME=\"description\" CONTENT=\"Output (supporto) del programma");
fprintf(file," per il calcolo di supporto e confidenza di Daniele Rampoldi\">\n");
fprintf(file,"<META NAME=\"keywords\" CONTENT=\"apriori,supporto,daniele rampoldi\">");
fprintf(file,"\n\n<title>Supporti</title>\n\n</head><body>\n\n");

fprintf(file,"<body bgcolor=white text=black link=\"#00aa00\" vlink=\"#606060\" alink=\"#0000aa\">");
fprintf(file,"\n<br><br>\n<h1 align=\"center\">Supporti calcolati</h1>\n<br>\n\n");
fprintf(file,"<TABLE border=1 cellpadding=5 align=center>\n\n");
fprintf(file,"<tr><td align=center><font size=+1><b>Transazione</b></font></td>\n");
fprintf(file,"<td align=center><font size=+1><b>Supporto</b></font></td></tr>\n\n");

fprintf(stderr,"\nScrittura del file supp.html (supporto) in corso ");
tp1=clock();
fprintf(stderr,"(Secondi trascorsi: %7.3lf)\n",(tp1-tp0)/(double)CLOCKS_PER_SEC);

sup=scrivisupp(file,sup,root1);		/* scrittura su file degli item-set frequenti con relativo supporto */

fprintf(file,"\n</table>\n</body>\n</html>\n");
fclose(file);



file=fopen("conf.html","w");
if(file==NULL)
	{fprintf(stderr,"Problema nell\'apertura del file conf.html\n");
	 return 0;
	}

fprintf(file,"<html>\n<head>\n<META NAME=\"DC.Title\" CONTENT=\"Confidenza\">");
fprintf(file,"\n<META NAME=\"description\" CONTENT=\"Output (confidenza) del programma");
fprintf(file," per il calcolo di supporto e confidenza di Daniele Rampoldi\">\n");
fprintf(file,"<META NAME=\"keywords\" CONTENT=\"apriori,confidenza,daniele rampoldi\">");
fprintf(file,"\n\n<title>Confidenze</title>\n\n</head><body>\n\n");

fprintf(file,"<body bgcolor=white text=black link=\"#00aa00\" vlink=\"#606060\" alink=\"#0000aa\">");
fprintf(file,"\n<br><br>\n<h1 align=\"center\">Confidenze calcolate</h1>\n<br>\n\n");
fprintf(file,"<TABLE border=1 cellpadding=5 align=center>\n\n");

fprintf(file,"<tr><td align=center><font size=+1><b>Regola</b></font></td>\n");
fprintf(file,"<td align=center><font size=+1><b>Supporto Primo Termine</b></font></td>\n");
fprintf(file,"<td align=center><font size=+1><b>Supporto Totale</b></font></td>\n");
fprintf(file,"<td align=center><font size=+1><b>Confidenza</b></font></td></tr>\n\n");

fprintf(stderr,"\nScrittura del file conf.html (confidenza) in corso ");
tp1=clock();
fprintf(stderr,"(Secondi trascorsi: %7.3lf)\n",(tp1-tp0)/(double)CLOCKS_PER_SEC);

scriviconf(file,tri,root1);		/* scrittura su file delle regole frequenti con relativa confidenza */

fprintf(file,"\n</table>\n</body>\n</html>\n");
fclose(file);

fprintf(stderr,"\n**********ESECUZIONE COMPLETATA**********\n\n");

return 1;
}








/*
liv -->  albero binario di livello 1
l --> prodotto
conn2 --> connessione alternativa al database
*/

struct liv1 *aggliv1(struct liv1 *liv,int l,PGconn *conn2)
{
PGresult *res2;
char richiesta[256];
char t[10];

if(liv==NULL)		/* nuovo prodotto */
	{strcpy(richiesta,"DECLARE pr CURSOR FOR SELECT SPIEGAZIONE FROM PRODOTTI WHERE N=\0");
	 sprintf(t,"%d",l);
	 strcat(richiesta,t);
	 
	 res2=PQexec(conn2,"BEGIN");
	 if(PQresultStatus(res2)!=PGRES_COMMAND_OK)
		{fprintf(stderr,"Comando BEGIN fallito: %s\n",PQerrorMessage(conn2));
		 PQclear(res2);
		 PQfinish(conn2);
		 return NULL;
		}

	 PQclear(res2);
	 res2=PQexec(conn2,richiesta);
	 if(PQresultStatus(res2)!=PGRES_COMMAND_OK)
		{fprintf(stderr,"Comando CURSOR fallito: %s\n",PQerrorMessage(conn2));
		 PQclear(res2);
		 PQfinish(conn2);
		 return NULL;
		}

	 PQclear(res2);
	 res2=PQexec(conn2,"FETCH ALL in pr");
	 if(PQresultStatus(res2)!=PGRES_TUPLES_OK)
		{fprintf(stderr,"Comando FETCH ALL fallito: %s\n",PQerrorMessage(conn2));
		 PQclear(res2);
		 PQfinish(conn2);
		 return NULL;
		}
	 if(PQntuples(res2)>1)
	 	{fprintf(stderr,"Errore: il numero di righe restituite per un prodotto e\' maggiore di 1\n");
	 	 return NULL;
		}

	 liv=(struct liv1 *)malloc(sizeof(struct liv1));
	 liv->left=liv->right=NULL;
	 liv->freq=1;
	 liv->n=l;
	 strcpy(liv->spiegazione,PQgetvalue(res2,0,0));
	 PQclear(res2);
	 res2=PQexec(conn2,"CLOSE pr");
	 if(PQresultStatus(res2)!=PGRES_COMMAND_OK)
		{fprintf(stderr,"Comando CLOSE fallito: %s\n",PQerrorMessage(conn2));
		 PQclear(res2);
		 PQfinish(conn2);
		 return NULL;
		}
	 PQclear(res2);
	 res2=PQexec(conn2,"END");
	 if(PQresultStatus(res2)!=PGRES_COMMAND_OK)
		{fprintf(stderr,"Comando END fallito: %s\n",PQerrorMessage(conn2));
		 PQclear(res2);
		 PQfinish(conn2);
		 return NULL;
		}
	 PQclear(res2);
	 return liv;
	}

/* se sono qua e' perche' non sono arrivato ad una foglia (liv!=NULL) */
if(liv->n==l)		/* ho trovato il prodotto nell'albero */
	{liv->freq++;
	 return liv;
	}

if(liv->n<l)
	{liv->right=aggliv1(liv->right,l,conn2);
	 return liv;
	}

if(liv->n>l)
	{liv->left=aggliv1(liv->left,l,conn2);
	 return liv;
	}

fprintf(stderr,"Se sono arrivato qui c\'e\' un errore (funzione aggliv1)\n");
return liv;
}









void taglia(struct liv1 *liv,int livello)
{
if(liv!=NULL)
	taglia(liv->left,livello);
else
	return;

/* ora sono nella corrente (che non e' NULL) */
if(liv->freq>=soglia)
	{cuci(root1,liv->n,livello);
	 outh3=insout(livello,liv->n,liv->freq,outh3);
	}

/* ora cerco nelle maggiori (a destra) */
taglia(liv->right,livello);
}





/*
questa funzione serve per prendere i prodotti frequenti (di livello 1)
e unirli per trovare le transazioni di grandezza 2 candidate ad essere frequenti
*/

void cuci(struct liv1 *r1,int a,int livello)
{
if(r1==NULL)
	return;

if(r1->n<a)
	{cuci(r1->right,a,livello);
	 return;
	}

if(r1->n>a)
	{if(r1->freq>=soglia)
		scrivi2(a,r1->n);
	 cuci(r1->left,a,livello);
	}

cuci(r1->right,a,livello);

}








/* inserimento in lista stabile di output a livello 1 */
/* devo inserire a in struct h3 *outh3 al livello="liv-1" */
struct h3 *insout(int liv,int a,int fr,struct h3 *out)
{
struct transaz *li;
int z;


liv--;

if(out==NULL)
	{out=(struct h3 *)malloc(sizeof(struct h3));
	 out->lista=NULL;
	 for(z=0;z<10;z++)
		out->next[z]=NULL;
	}

if(liv==0)
	{li=out->lista;
	 out->lista=(struct transaz *)malloc(sizeof(struct transaz));
	 out->lista->n=(int *)calloc(2,sizeof(int));
	 out->lista->n[0]=a;
	 out->lista->n[1]=out->lista->id=0;
	 out->lista->grand=1;
	 out->lista->freq=fr;
	 out->lista->next=li;
	 return out;
	}

fprintf(stderr,"Se sono qui c\'e\' un errore (funzione insout)\n");
return NULL;

}







/* devo scrivere la coppia (a,n) in struct h3 *rooth3 a livello=2 */
void scrivi2(int a,int n)
{
int z,z2;
struct transaz *r;

if(rooth3==NULL)
	{rooth3=(struct h3 *)malloc(sizeof(struct h3));
	 rooth3->lista=NULL;
	 for(z=0;z<10;z++)
		rooth3->next[z]=NULL;
	}

z=a%10;

if(rooth3->next[z]==NULL)
	{rooth3->next[z]=(struct h3 *)malloc(sizeof(struct h3));
	 rooth3->next[z]->lista=NULL;
	 for(z2=0;z2<10;z2++)
	 	rooth3->next[z]->next[z2]=NULL;
	}

r=rooth3->next[z]->lista;
rooth3->next[z]->lista=(struct transaz *)malloc(sizeof(struct transaz));
rooth3->next[z]->lista->n=(int *)calloc(3,sizeof(int));
rooth3->next[z]->lista->n[0]=a;
rooth3->next[z]->lista->n[1]=n;

rooth3->next[z]->lista->n[2]=rooth3->next[z]->lista->id=0;
rooth3->next[z]->lista->grand=2;
rooth3->next[z]->lista->freq=0;
rooth3->next[z]->lista->next=r;

}




/* QUI TERMINANO LE FUNZIONI A LIVELLO 1 */



struct transaz *alltransaz(int n,struct transaz *nex)
{
struct transaz *t;

t=(struct transaz *)malloc(sizeof(struct transaz));
t->id=0;
t->n=(int *)calloc(n,sizeof(int));
t->n[0]=0;
t->grand=t->freq=0;
t->next=nex;

return t;
}







struct transaz *prenditr(PGresult *res,struct transaz *t)
{
/* utilizzo t->freq (intero) per riga a cui sono arrivato */

int idd,tra;

t->id=atoi(PQgetvalue(res,t->freq,0));
t->n[0]=atoi(PQgetvalue(res,t->freq,1));
t->freq++;
t->grand=1;


if(t->freq>=PQntuples(res))
	{t->n[t->grand]=0;
	 return t;
	}

idd=atoi(PQgetvalue(res,t->freq,0));
while(idd==t->id)
	{tra=atoi(PQgetvalue(res,t->freq,1));
	 if(tra==t->n[t->grand-1])	/* in ogni singola transazione non ci interessano gli elementi doppi */
	 	{t->freq++;
	 	 if(t->freq>=PQntuples(res))
			{t->n[t->grand]=0;
			 return t;
			}
		 idd=atoi(PQgetvalue(res,t->freq,0));
		 continue;
		}
	 t->n[t->grand]=tra;
	 t->grand++;
	 t->freq++;
	 if(t->freq>=PQntuples(res))
		{t->n[t->grand]=0;
		 return t;
		}
	 idd=atoi(PQgetvalue(res,t->freq,0));
	}

/* se c'e' una transazione successiva, ma l'id e' diverso */
t->n[t->grand]=0;


return t;
}






/* lucido 32 */
void conta(struct transaz *t,struct h3 *n,int i,int l,int dove)
{
int j,f;

if(n==NULL)
	return;

if(l==livello-1)	/* se sono in una foglia */
	{discesa[dove]=0;
	 incrementa(t,n->lista);
	 return;
	}

if(i<t->grand)
	{for(j=i;j<t->grand;j++)
		{f=(t->n[j])%10;
		 discesa[dove]=t->n[j];
		 conta(t,n->next[f],j,l+1,dove+1);
		}
	}

}







/*
t --> transazione
l --> lista
*/
void incrementa(struct transaz *t,struct transaz *l)
{
int i,j=0;
int k;


if(l==NULL)
	return;

for(i=0;i<livello-1;i++)	/* per il problema della sovrapposizione degli hash */
	{if(discesa[i]!=l->n[i])
		break;
	}

if(i==livello-1)	/* devo controllare l'ultimo numero e se e' tutto ok incremento, altrimenti continuo */
	{k=0;
	 for(j=0;j<t->grand;j++)
	 	{if(l->n[i]==t->n[j])
			{k=1;
			 break;
			}
		}
	 if(k==1)
	 	l->freq++;
	}

incrementa(t,l->next);
/* N.B.:la transazione e' (di solito) piu' lunga della lunghezza di l */
}







/* liv = 2 al primo giro (dopo aver contato le transazioni a livello 2) */
struct h3 *unisci(struct h3 *z,int liv,struct h3 *r,int lcorr)
{
/*
in *z ho le transazioni di livello=liv con relative frequenze.
--> vado in ogni ramo fino a liv-1 --> vado nella lista
--> se gli elementi dallo 0 a liv-2 sono uguali e freq>soglia
--> unisco gli elementi e li metto in *r (per il prossimo livello)
--> contemporaneamente inserisco a livello=liv-1
--> scriviout(liv,int *elem) (lista stabile)
--> inoltre int lcorr (livello corrente) = 0 all'inizio
*/

int i;
struct transaz *a;
struct transaz *b;
struct transaz *c;


if(z==NULL)
	return r;

if(lcorr!=liv-1)
	{for(i=0;i<10;i++)
		{r=unisci(z->next[i],liv,r,lcorr+1);
		}
	 return r;
	}
a=z->lista;
while(a!=NULL && a->freq<soglia)
	{c=a;
	 a=a->next;
	 free(c->n);
	 free(c);
	}
if(a==NULL)
	return r;

outh3=scriviout(a,liv,0,outh3);		/* scrivo nell'output stabile l'elemento trovato */

b=a->next;
while(b!=NULL && b->freq<soglia)
	b=b->next;
if(b==NULL)
	return r;

while(a!=NULL)
	{while(b!=NULL)
		{for(i=0;i<(b->grand)-1;i++)
			{if(a->n[i]!=b->n[i])
				break;
			}
		 if(i==(b->grand)-1)
		 	{/* sono uguali --> li copio */
		 	 r=copia(r,a,b,liv,0);
			}
		 b=b->next;
		 while(b!=NULL && b->freq<soglia)
		 	b=b->next;
		 if(b==NULL)
		 	break;		/* esci dal while(b) */
		}				/* fine del while(b) */
	 c=a;
	 a=a->next;
	 free(c->n);
	 free(c);
	 while(a!=NULL && a->freq<soglia)
	 	{c=a;
	 	 a=a->next;
	 	 free(c->n);
	 	 free(c);
		}
	 if(a==NULL)
		return r;
	 outh3=scriviout(a,liv,0,outh3);
	 b=a->next;
	 while(b!=NULL && b->freq<soglia)
		b=b->next;
	 if(b==NULL)
	 	return r;
	}			/* fine del while(a) */

}









/*
liv --> livello di *a e *b
lcorr (livello corrente) --> =0 all'inizio
*/
struct h3 *copia(struct h3 *r,struct transaz *a,struct transaz *b,int liv,int lcorr)
{
int i,f;
struct transaz *z;


if(r==NULL)
	{r=(struct h3 *)malloc(sizeof(struct h3));
	 r->lista=NULL;
	 for(i=0;i<10;i++)
		r->next[i]=NULL;
	}

if(lcorr!=liv)
	{if(b->n[lcorr]<a->n[lcorr])		/* per l'ultimo elemento della lista della transazione */
		f=(b->n[lcorr])%10;
	 else
	 	f=(a->n[lcorr])%10;
	 r->next[f]=copia(r->next[f],a,b,liv,lcorr+1);
	 return r;
	}

/* se sono qui --> sono arrivato al livello giusto --> devo inserire il nuovo elemento */
z=(struct transaz *)malloc(sizeof(struct transaz));
z->id=z->freq=0;
z->n=(int *)calloc(liv+2,sizeof(int));
z->grand=liv+1;
z->next=r->lista;
r->lista=z;

for(i=0;i<liv-1;i++)
	z->n[i]=a->n[i];

if(a->n[liv-1]<b->n[liv-1])
	{z->n[liv-1]=a->n[liv-1];
	 z->n[liv]=b->n[liv-1];
	}
else
	{z->n[liv-1]=b->n[liv-1];
	 z->n[liv]=a->n[liv-1];
	}
z->n[liv+1]=0;

return r;
}











/* inserisco in struct h3 *outh3 (lista stabile di output) a livello=liv-1 l'elemento a */
struct h3 *scriviout(struct transaz *a,int liv,int lcorr,struct h3 *o)
{
int i,f;
struct transaz *z;

if(o==NULL)
	{o=(struct h3 *)malloc(sizeof(struct h3));
	 o->lista=NULL;
	 for(i=0;i<10;i++)
		o->next[i]=NULL;
	}

if(lcorr!=liv-1)
	{f=(a->n[lcorr])%10;
	 o->next[f]=scriviout(a,liv,lcorr+1,o->next[f]);
	 return o;
	}

z=(struct transaz *)malloc(sizeof(struct transaz));
z->id=0;
z->n=(int *)calloc((a->grand)+1,sizeof(int));
z->grand=a->grand;
z->freq=a->freq;
z->next=o->lista;
o->lista=z;

for(i=0;i<a->grand;i++)
	{z->n[i]=a->n[i];
	}
z->n[z->grand]=0;

return o;
}










/*
devo tagliare --> controllo tutti i sottoins. dei nuovi accoppiamenti
--> devono essere presenti nella lista del livello precedente --> se no -->taglio
n.b.:i nuovi sono generati dai 2 vecchi con i primi "livello" elementi uguali

In particolare tutti i sottoinsiemi di ogni transazione di r a livello=liv
devono essere presenti in o a livello=liv-1

Quindi:
	1-prima vado in r a livello=liv (ogni ramo)
	2-per ogni transazione in r->foglia --> cerca(transaz,liv,o)
*/
struct h3 *taglia2(struct h3 *r,int liv,struct h3 *o,int lcorr)
{
int i;
struct transaz *f;
struct transaz *f2;

if(r==NULL)
	return r;

if(liv!=lcorr)
	{for(i=0;i<10;i++)
		r->next[i]=taglia2(r->next[i],liv,o,lcorr+1);
	 return r;
	}

inizio:
	f=r->lista;
	if(f==NULL)
		return r;

	i=cerca(f,liv,o);	/* =0 --> elimina +++++ =1 -->ok */
	if(i==0)
		{r->lista=f->next;
		 free(f->n);
		 free(f);
		 goto inizio;
		}

f2=f;
f=f->next;
while(f!=NULL)
	{i=cerca(f,liv,o);
	 if(i==0)
	 	{f2->next=f->next;
	 	 free(f->n);
	 	 free(f);
	 	 f=f2->next;
		}
	 else
	 	{f2=f;
	 	 f=f->next;
		}
	}

return r;
}









/*
ritorna:
	0 --> elimina
	1 --> ok
*/
int cerca(struct transaz *f,int liv,struct h3 *o)
{
struct transaz *f2;
int i,j,k;

f2=(struct transaz *)malloc(sizeof(struct transaz));
f2->n=(int *)calloc((f->grand)-1,sizeof(int));
f2->id=f2->freq=0;
f2->next=NULL;
f2->grand=(f->grand)-1;

/* ora per ogni sottoinsieme f2 di f cerco f2 in o a livello=liv-1 */
for(i=0;i<(f->grand)-2;i++)
	{/* i rappresenta l'elemento che tolgo */
	 k=0;
	 for(j=0;j<(f->grand);j++)
	 	{if(j==i)
	 		continue;
	 	 else
	 	 	{f2->n[k]=f->n[j];
	 	 	 k++;
			}
		}
	 j=cerca2(f2,o,liv);	/* se =0 --> non trovato */
	 if(j==0)
	 	{free(f2->n);
	 	 free(f2);
	 	 return 0;
		}
	}
free(f2->n);
free(f2);

return 1;
}









/* cerco f2 in o a livello=liv-1 --> se lo trovo --> torna 1 --> altrimenti --> 0 */
int cerca2(struct transaz *f2,struct h3 *o,int liv)
{
int lcorr=0;
int s,i;
struct h3 *z;
struct transaz * f3;

z=o;
while(lcorr!=liv-1)
	{if(z==NULL)
		return 0;
	 s=(f2->n[lcorr])%10;
	 z=z->next[s];
	 lcorr++;
	}

if(z==NULL)
	return 0;

f3=z->lista;

while(f3!=NULL)
	{for(i=0;i<f2->grand;i++)
		{if(f2->n[i]!=f3->n[i])
			break;
		}
	 if(i==f2->grand)	/* l'ho trovato */
	 	return 1;
	 f3=f3->next;
	}

return 0;		/* se f3==NULL sono alla fine */
}








/* devo pulire: t --> no lista, solo next
		r --> controlla i *lista */
struct h3 *pulisci(struct h3 *t,struct h3 *r)
{
pul(t);
r=isci(r);


return r;
}









void pul(struct h3 *t)
{
int i;

if(t==NULL)
	return;

for(i=0;i<10;i++)
	pul(t->next[i]);

free(t);

}









struct h3 *isci(struct h3 *r)
{
int i,j=0;

if(r==NULL)
	return NULL;

for(i=0;i<10;i++)
	{r->next[i]=isci(r->next[i]);
	 if(r->next[i]!=NULL)
	 	j=1;
	}

if(j==1)
	return r;
else		/* tutti i figli == NULL */
	{if(r->lista!=NULL)
		return r;
	 else
	 	{free(r);
	 	 return NULL;
		}
	}

}









/*
1 - scorro o
2 - per ogni elem. in o --> lo inserisco in s (ordinato per supporto)
						--> cerco tutte le relazioni possibili tra gli elementi
							(relazioni in cui siano presenti tutti gli elementi)
							se ne trovo con conf > sogliac
						--> li inserisco in tri (ordinato per confidenza)
*/
struct h3 *suppconf(struct h3 *o)
{
int i;
struct transaz *l;

if(o==NULL)
	return o;

for(i=0;i<10;i++)
	o->next[i]=suppconf(o->next[i]);

l=o->lista;
if(l==NULL)
	return o;

while(l!=NULL)
	{sup=inss(l,sup);
	 insc(l);
	 l=l->next;
	}


return o;
}








struct supp *inss(struct transaz *l,struct supp *s)
{
int i;
float ii;


if(s==NULL)
	{s=(struct supp *)malloc(sizeof(struct supp));
	 s->elem=(int *)calloc((l->grand)+1,sizeof(int));
	 s->supp=((float)l->freq)/((float)ntransaz);	/* calcolo del supporto */
	 for(i=0;i<l->grand;i++)
	 	s->elem[i]=l->n[i];
	 s->elem[i]=0;
	 s->dx=s->sx=s->cen=NULL;
	 return s;
	}

ii=((float)l->freq)/((float)ntransaz);	/* calcolo del supporto (per confronto nell'albero binario) */
if(ii<s->supp)
	s->sx=inss(l,s->sx);
else
	if(ii>s->supp)
		s->dx=inss(l,s->dx);
	else
		s->cen=inss(l,s->cen);

return s;
}









void insc(struct transaz *l)
{
int **p;
int *corr;
int i,k;

p=(int **)calloc(1000,sizeof(int *));

for(i=0;i<1000;i++)
	p[i]=NULL;
corr=(int *)calloc(l->grand,sizeof(int));

for(i=1;i<l->grand;i++)
	{p=estrai(i,l->n,l->grand,p,corr,0);
	 cercaconf(p,l);
	 k=0;
	 while(p[k]!=NULL)
	 	{free(p[k]);
	 	 p[k]=NULL;
	 	 k++;
		}
	}

free(p);

}











/*
n     --> quanti devo estrarne
lista --> lista da cui pescare
grand --> grandezza della lista "lista"
p     --> output
corr  --> lista in cui inserire
ora   --> dove inserire in corr
*/
int **estrai(int n,int *lista,int grand,int **p,int *corr,int ora)
{
int i,j,k;
int *l2;
int **p2;

if(grand<1)
	return p;

if(n!=1)
	{l2=(int *)calloc(grand,sizeof(int));
	 for(i=0;i<grand;i++)
	 	{corr[ora]=lista[i];
	 	 k=0;
	 	 for(j=i+1;j<grand;j++)
	 	 	{l2[k]=lista[j];
	 	 	 k++;
			}
		 p=estrai(n-1,l2,grand-1-i,p,corr,ora+1);
		}
	 free(l2);
	 return p;
	}


/* se n==1 */
corr[ora]=lista[0];
i=k=0;

qui:
	while(p[k]!=NULL)
		{k++;
		 if(k%1000==0)
		 	{p2=(int **)calloc(k+1000,sizeof(int *));
		 	 for(j=0;j<k;j++)
		 	 	p2[j]=p[j];
		 	 for(j=k;j<k+1000;j++)
		 	 	p2[j]=NULL;
		 	 free(p);
		 	 p=p2;
			}
		}
	p[k]=(int *)calloc(ora+2,sizeof(int));
	for(j=0;j<=ora;j++)
		p[k][j]=corr[j];
	p[k][j]=0;
	if(grand>1)
		{i++;
		 k++;
		 corr[ora]=lista[i];
		 grand--;
		 goto qui;
		}

return p;
}









/*
p --> da
l --> totale
*/
void cercaconf(int **p,struct transaz *l)
{
/*
prima cerco da in outh3 (per ogni elemento in p) --> c'e' sicuramente
poi calcolo la confidenza --> se oltre la soglia della confidenza
--> inserisco il tutto in tri. Se no passo al successivo
*/

int i,j,k,w;
float suppda,conf,supptot;
int *a;

k=0;
a=(int *)calloc(l->grand,sizeof(int));

while(p[k]!=NULL)
	{suppda=cercaconf2(p[k],outh3,0);		/* supporto del "da" */
	 supptot=((float)l->freq/(float)ntransaz);	/* supporto totale */
	 conf=supptot/suppda;				/* confidenza */

	 if(conf<limconf)		/* il livello di confidenza e' inferiore alla soglia */
	 	{k++;
	 	 continue;		/* passo al successivo */
		}
	 i=j=0;
	 for(w=0;w<l->grand;w++)
	 	{if(p[k][i]==l->n[w])
	 		i++;
	 	 else
	 	 	{a[j]=l->n[w];	/* estraggo dal "totale" il "a" */
	 	 	 j++;
			}
		}
	 a[j]=0;
	 tri=insconf(p[k],a,suppda,supptot,conf,tri);	/* inserisco in tri da --> a e i valori di supporto e confidenza */
	 k++;
	}

free(a);
}









/* cerco da (fino allo 0) in o e ritorno il supporto (come float) */
float cercaconf2(int *da,struct h3 *o,int liv)
{
int i,f;
float f2;
struct transaz *l;

if(da[liv+1]!=0)	/* se lungh=3 --> liv=2 --> liv+1=3 --> da={'a','b','c',0} */
	{f=da[liv]%10;											 /*  0   1   2  3  */
	 f2=cercaconf2(da,o->next[f],liv+1);
	 return f2;
	}

/* da[liv+1]==0 --> sono arrivato dove volevo */

l=o->lista;
while(l!=NULL)
	{for(i=0;i<l->grand;i++)
		{if(l->n[i]!=da[i])
			break;
		}
	 if(i==l->grand)
	 	{f2=((float)l->freq/(float)ntransaz);
	 	 return f2;
		}
	 else
	 	l=l->next;
	}

fprintf(stderr,"Se sono arrivato qui e\' perche\' non ho trovato il \"da\" --> E\' UN ERRORE!!!");
fprintf(stderr," (funzione cercaconf2)\n");

return 0;
}










/*
pk      --> da
a       --> a
suppda  --> supporto di "da"
supptot --> supporto totale
conf    --> confidenza
t       --> albero trinario
*/
struct trin *insconf(int *pk,int *a,float suppda,float supptot,float conf,struct trin *t)
{
int lungh,i;

if(t==NULL)
	{t=(struct trin *)malloc(sizeof(struct trin));
	 lungh=intlen(pk);
	 t->da=(int *)calloc(lungh+1,sizeof(int));
	 for(i=0;i<lungh;i++)
	 	t->da[i]=pk[i];
	 t->da[i]=0;
	 lungh=intlen(a);
	 t->a=(int *)calloc(lungh+1,sizeof(int));
	 for(i=0;i<lungh;i++)
	 	t->a[i]=a[i];
	 t->a[i]=0;
	 t->suppda=suppda;
	 t->supptot=supptot;
	 t->conf=conf;
	 t->dx=t->sx=t->cen=NULL;
	 return t;
	}

/* qui t!=NULL */
if(conf<t->conf)
	{t->sx=insconf(pk,a,suppda,supptot,conf,t->sx);
	 return t;
	}

if(conf>t->conf)
	{t->dx=insconf(pk,a,suppda,supptot,conf,t->dx);
	 return t;
	}

if(conf==t->conf)
	{t->cen=insconf(pk,a,suppda,supptot,conf,t->cen);
	 return t;
	}

fprintf(stderr,"Sono qui per errore nella funzione insconf\n");
return t;
}










struct supp *scrivisupp(FILE *file,struct supp *sup,struct liv1 *r1)
{
/* ho appena fatto <table> e chiudo appena prima di </table> */
/* ogni riga sara' del tipo <tr><td align=center> ... </td>
	<td align=center> ... </td> ..... <tr> ....... </tr> */

int k;
char *spiegaz;


if(sup==NULL)
	return sup;

if(sup->dx!=NULL)
	{sup->dx=scrivisupp(file,sup->dx,r1);}
if(sup->cen!=NULL)
	{sup->cen=scrivisupp(file,sup->cen,r1);}


/* ora scrivo il corrente */
fprintf(file,"<tr><td align=center>");
k=0;

spiegaz=(char *)calloc(256,sizeof(char));
while(sup->elem[k]!=0)
	{spiegaz=trovaspiegaz(sup->elem[k],r1,spiegaz);
	 if(k==0)
	 	fprintf(file,"{\'%s\'",spiegaz);
	 else
	 	fprintf(file,",\'%s\'",spiegaz);
	 k++;
	}
free(spiegaz);
fprintf(file,"}</td><td align=center>%.3f</td></tr>\n",sup->supp);


if(sup->sx!=NULL)
	sup->sx=scrivisupp(file,sup->sx,r1);

free(sup->elem);
free(sup);

sup=NULL;
return sup;
}











void scriviconf(FILE *file,struct trin *tri,struct liv1 *root1)
{
int k;
char *spiegaz;

if(tri==NULL)
	return;

if(tri->dx!=NULL)
	scriviconf(file,tri->dx,root1);

if(tri->cen!=NULL)
	scriviconf(file,tri->cen,root1);

/* ora scrivo il corrente */

fprintf(file,"<tr><td align=center>");
k=0;

spiegaz=(char *)calloc(256,sizeof(char));
while(tri->da[k]!=0)
	{spiegaz=trovaspiegaz(tri->da[k],root1,spiegaz);
	 if(k==0)
	 	fprintf(file,"{\'%s\'",spiegaz);
	 else
	 	fprintf(file,",\'%s\'",spiegaz);
	 k++;
	}
fprintf(file,"} --> ");

k=0;
while(tri->a[k]!=0)
	{spiegaz=trovaspiegaz(tri->a[k],root1,spiegaz);
	 if(k==0)
	 	fprintf(file,"{\'%s\'",spiegaz);
	 else
	 	fprintf(file,",\'%s\'",spiegaz);
	 k++;
	}
free(spiegaz);
fprintf(file,"}</td><td align=center>%.3f</td><td align=center>%.3f</td><td align=center>%.3f</td></tr>\n",tri->suppda,tri->supptot,tri->conf);

if(tri->sx!=NULL)
	scriviconf(file,tri->sx,root1);

free(tri->da);
free(tri->a);
free(tri);
}












char *trovaspiegaz(int n,struct liv1 *r,char *s)
{
if(r==NULL)
	{strcpy(s,"non trovato");
	 return s;
	}

if(n<r->n)
	{s=trovaspiegaz(n,r->left,s);
	 return s;
	}

if(n>r->n)
	{s=trovaspiegaz(n,r->right,s);
	 return s;
	}

if(n==r->n)
	{strcpy(s,r->spiegazione);
	 return s;
	}

strcpy(s,"Se sono qui e\' perche\' c\'e\' un errore nella funzione trovaspiegaz");
return s;
}










/* ritorna la lunghezza dell'array di interi s (utilizzata nella funzione insconf) */
int intlen(int *s)
{
int i=0;

while(s[i]!=0)
	i++;

return i;
}












/* Torna alla pagina principale
Leggi il codice di apriori_next.c */






  Indice principale     Indice dei Programmi     Indice del Progetto di BDD(cp)  

Data creazione: 17 Settembre 2010
Data ultima modifica: 30 Dicembre 2012