/**
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
**/
#include "iaesa.h"
nodo *mejores;
Tdist **DISTANCIAS;
Tdist dame_distancia(int x, int y)
{
return DISTANCIAS[x][y];
}
Index build (char *dbname, int n, int *argc, char ***argv)
{
fq *a;
a = (fq *)malloc(sizeof(struct t_fq));
a->dbname = malloc(strlen(dbname)+1);
strcpy(a->dbname, dbname);
a->np = openDB(dbname);
if (n && (n < a->np)) a->np = n;
a->tamEtiq = 30; //just to realloc
elem = (obj_gcv *)malloc(a->np * sizeof(struct elem_caja));
llena_arreglo_con_elementos_bd(a->np, a->np);
//prnstats((Index)a);
return (Index)a;
}
/************** COMPARACIONES ENTRE OBJETOS *******************/
int compara(const void *a, const void *b)
{
Id_Dist *x = (Id_Dist *) a;
Id_Dist *y = (Id_Dist *) b;
if(x->d > y->d) return 1;
if(x->d < y->d) return -1;
return 0;
}
int compara_dobleEnteros(const void *a, const void *b)
{
dobleEntero *x, *y;
x = (dobleEntero *) a;
y = (dobleEntero *) b;
if(x->lcs > y->lcs) return 1;
if(x->lcs < y->lcs) return -1;
return 0;
}
void actualiza_lista(int indice, int *ant, int *sig, int *inicio)
{
if(*inicio == indice)
*inicio = elem[indice].sig;
if(*ant == indice)
*sig = *ant = elem[indice].sig;
else // ant no cambia
{
elem[*ant].sig = *sig = elem[indice].sig;
}
elem[indice].sig = -1;
}
void eliminar_elemento(int indice, int *ant, int *sig, int *eliminados, int *inicio)
{
if(elem[indice].marcado == 0)
(*eliminados)++;
elem[indice].marcado = 1;
if(elem[indice].etiqueta != NULL)
{
free(elem[indice].etiqueta);
elem[indice].etiqueta = NULL;
}
}
/*********************** BUSQUEDA *************************************/
int search(Index S, Obj obj, Tdist r, bool show)
{
return search_metodo(S, obj, r, show, _Iaesa_);
}
void inicializa_etiquetas(fq *a)
{
int i;
for(i=0; inp; i++)
{
elem[i].etiqueta = malloc(sizeof(int) * a->tamEtiq);
elem[i].inversa = malloc(sizeof(int) * a->tamEtiq);
}
}
int search_metodo(Index S, Obj obj, Tdist r, bool show, char funcion)
{
fq *a;
int eliminados=0, sig=0, indice, siguiente, cont=0, num=0, ant;
Tdist d;
a = (fq *)S;
mejores = (nodo *) malloc(a->np*sizeof(nodo));
limpia_marcados(a->np);
inicializa_etiquetas(a);
sig = indice = 0;
while(eliminados < a->np && indice != -1)
{
eliminar_elemento(indice, &ant, &siguiente, &eliminados, &sig);
d = distance(obj, elem[indice].obj);
mejores[num].elem = indice;
mejores[num++].d = d;
if(d <= r)
{
cont++;
if(show)
printobj(elem[indice].obj);
}
marca_elementos_descartados(indice, a->np, &sig, r, &eliminados, d, num-1);
indice = escoge_siguiente(&sig, a->np, num, obj, a, funcion);
ant = siguiente = sig;
}
free(mejores);
return cont;
}
/*********************** funciones utiles ******************************************/
int distPosicion(int tam, int *etiqInv, int *y, int *x_toda, fq *a, int indice)
{
int i, t, total=0;
// static int *temp = NULL;
// if(temp == NULL)
// temp = (int *)malloc(a->np * sizeof(int));
// for(i=0; i 0 ? t : t*-1;
// total += abs((i-etiqInv[y[i]]));
total += t * t;
}
return total;
}
void imprime_permutacion(int *p, int tam)
{
int i;
printf("p[");
for(i=0; itamEtiq;
int *nueva = malloc(sizeof(int) * a->tamEtiq * (multiplo+1));
int *InvNueva = malloc(sizeof(int) * a->tamEtiq * (multiplo+1));
for(i=0; itamEtiq < cont && cont % a->tamEtiq == 1) // solo debe actualizarse si es que es la$
reasignar_memoria(indice, cont, a);
(*permut)[cont-1] = cont-1;
v = dame_distancia(indice, mejores[cont-1].elem);
j=cont-1;
while(j > 0 && v < dame_distancia(indice, mejores[ (*permut)[j-1] ].elem) )
{
(*permut)[j] = (*permut)[j-1];
j--;
}
(*permut)[j] = cont-1;
}
// usando la inversa
int insertsort_elemento(int **permutU, int cont, int indice, int *etiqQinv,
int posicionQ, int *permutQ, fq *a)
{
int i, Sp=0, posU=0;
if(a->tamEtiq < cont && cont % a->tamEtiq == 1) // solo debe actualizarse si es que es la primera vez que se ocupa
reasignar_memoria(indice, cont, a);
for(i=0; i0 && v < mejores[ (*permut)[j-1] ].d)
{
(*permut)[j] = (*permut)[j-1];
j--;
}
(*permut)[j] = cont-1;
return j;
}
int* forma_canonica(int* x_toda, int tam, fq *a)
{
int i, *temp = NULL;
if(temp == NULL)
temp = (int *)malloc(tam * sizeof(int));
for(i=0; inp);
posicionQ = insertsort(&permut, cont); // la nueva permutacion de la consulta
etiquetaQinv = forma_canonica(permut, cont, a);
for(i=*ini; i!=-1; i=elem[i].sig) // busco cual es el siguiente mejor elemento
{
if(elem[i].marcado == 0)
{
sig = suma(i, cont, a->np, permut, a, posicionQ, etiquetaQinv, funcion);
if(sig < min || elegido == -1)
{
min = sig;
elegido = i;
}
}
}
free(etiquetaQinv);
return elegido;
}
int escoge_siguiente_desempate(int *ini, int tam, int cont, Obj obj, fq *a, char funcion)
{
int i, elegido=-1;
int min = -1, sig=0, posicionQ, *etiquetaQinv;
static int *permut = NULL;
if(permut == NULL)
permut = (int *) malloc(sizeof(int) * a->np);
posicionQ = insertsort(&permut, cont); // la nueva permutacion de la consulta
etiquetaQinv = forma_canonica(permut, cont, a);
for(i=*ini; i!=-1; i=elem[i].sig) // busco cual es el siguiente mejor elemento
{
if(elem[i].marcado == 0)
{
sig = suma(i, cont, a->np, permut, a, posicionQ, etiquetaQinv, funcion);
if(sig < min || elegido == -1)
{
min = sig;
elegido = i;
}
else
if(sig == min)
elegido = elem[i].dist_aprox < elem[elegido].dist_aprox ? i : elegido;
}
}
return elegido;
}
/*********************** otras ******************************************/
void llena_arreglo_con_elementos_bd(int num_palabras, int nPiv)
{
int i, j,k=0;
DISTANCIAS = (Tdist **)malloc(sizeof(Tdist *) * num_palabras);
for(i=0; i r)
#else
if(fabs(dame_distancia(i, mejores[j].elem) - mejores[j].d ) > r)
#endif
{
eliminar_elemento(i, &ant, &siguiente, eliminados, sig);
actualiza_lista(i, &ant, &siguiente, sig);
break;
}
}
if(j>num)
{
if(elem[i].marcado == 1)
actualiza_lista(i, &ant, &siguiente, sig);
else
{
if(ant != i)
elem[ant].sig = i;
ant = i;
siguiente = elem[ant].sig;
}
}
}
}
int escoge_siguiente_aleatorio(int *ini, int tam, int cont)
{
int i;
for(i=*ini; i!= -1; i=elem[i].sig)
{
if(elem[i].marcado == 0)
return i;
}
return -1;
}
int escoge_siguiente_dist(int *ini, int tam, int cont)
{
int i, prox=-1;
Tdist aux=(Tdist)0, min=(Tdist)1000; // la distancia max. en palabras es 20
for(i=*ini; i!= -1; i=elem[i].sig)
{
if(elem[i].marcado == 0)
{
aux = suma_dist(i, cont);
if(aux < min || prox == -1) // la primera vez es seguro que la minimiza
{
min = aux;
prox = i;
}
}
}
return prox;
}
int escoge_siguiente_dist_l1(int *ini, int tam, int cont)
{
int i, prox=-1, bandera=0;
Tdist aux, min=300; // la distancia max. en palabras es 20
for(i=*ini; i!= -1; i=elem[i].sig)
{
if(elem[i].marcado == 0)
{
aux = suma_dist_l1(i, cont);
if(aux < min) // la primera vez es seguro que la minimiza
{
min = aux;
prox = i;
if(bandera==0)
{
*ini=i;
bandera = 1;
}
}
}
}
return prox;
}
Tdist suma_dist(int indice, int cont)
{
#ifdef DISCR
elem[indice].dist_aprox += abs(mejores[cont-1].d - dame_distancia(indice, mejores[cont-1].elem));
#else
elem[indice].dist_aprox += fabs(mejores[cont-1].d - dame_distancia(indice, mejores[cont-1].elem));
#endif
return elem[indice].dist_aprox;
}
Tdist suma_dist_l1(int indice, int cont)
{
Tdist d;
#ifdef DISCR
d = abs(mejores[cont-1].d - dame_distancia(indice, mejores[cont-1].elem));
#else
d = fabs(mejores[cont-1].d - dame_distancia(indice, mejores[cont-1].elem));
#endif
if(elem[indice].dist_aprox < d)
elem[indice].dist_aprox = d;
return elem[indice].dist_aprox;
}
Tdist sumaAESA(int indice, int cont)
{
Tdist resultado;
int j;
resultado = 0;
for(j=0; jdbname,strlen(a->dbname)+1,1,fp);
fwrite(&a->np, sizeof(int), 1, fp);
fwrite(&a->tamEtiq, sizeof(int), 1, fp);
for(i=0; inp; i++)
fwrite(&elem[i].obj, sizeof(Obj), 1, fp);
for(i=0; inp; i++)
for(j=0; jnp; j++)
fwrite(&DISTANCIAS[i][j], sizeof(Tdist), 1, fp);
fclose(fp);
}
Index loadIndex(char *fname)
{
char str[1024]; char *ptr = str;
long int j, i;
FILE *fp;
fq *a;
if( (fp=fopen(fname,"r")) == NULL )
{
fprintf(stderr,"Error loading file\n");
exit(-1);
}
a = (fq*) malloc(sizeof(fq) );
while ((*ptr++ = getc(fp)));
a->dbname = malloc (ptr-str);
strcpy (a->dbname,str);
fread(&a->np, sizeof(int), 1, fp);
fread(&a->tamEtiq, sizeof(int), 1, fp);
DISTANCIAS = (Tdist **) malloc(sizeof(Tdist *) * a->np);
elem = (obj_gcv *)malloc(a->np * sizeof(struct elem_caja));
for(i=0; inp; i++)
{
fread(&elem[i].obj, sizeof(Obj), 1, fp);
DISTANCIAS[i] = (Tdist *) malloc(sizeof(Tdist) * a->np);
}
for(i=0; inp; i++)
for(j=0; jnp; j++)
fread(&DISTANCIAS[i][j], sizeof(Tdist), 1, fp);
fclose(fp);
openDB(a->dbname);
return (Index)a;
}
void search_metodo_NN(Index S, Obj obj, int k, char funcion, Tcelem *res)
{
fq *a;
int eliminados=0, sig=0, indice, siguiente=0, num=0, ant=0;
Tdist d, r=(Tdist)10000;
a = (fq *)S;
mejores = (nodo *) malloc(a->np*sizeof(nodo));
limpia_marcados(a->np);
inicializa_etiquetas(a);
sig = indice = 0;
while(eliminados < a->np && indice != -1)
{
eliminar_elemento(indice, &ant, &siguiente, &eliminados, &sig);
d = distance(obj, elem[indice].obj);
mejores[num].elem = indice;
mejores[num++].d = d;
if(d <= r)
{
addCelem (res,elem[indice].obj,d);
if(res->csize >= k)
r = radCelem(res);
}
marca_elementos_descartados(indice, a->np, &sig, r, &eliminados, d, num-1);
indice = escoge_siguiente(&sig, a->np, num, obj, a, funcion);
ant = siguiente = sig;
}
free(mejores);
}