/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_ame.c                                                  */
/*                                                                          */
/*    (c) copyright 1992 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :  C. Sarwary                            le : 04/03/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/***************************************************************************/

#include <stdio.h>
#include <math.h>
#include MUT_H
#include LOG_H
#include "syf_auto.h"
#include "syf_must.h"
#include "../util/util.h"
/*---------------------------------------------------------------------------
recuit		: procede a un recuit simule pour trouver un codage optimal.
----------------------------------------------------
parametres	:
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
recuit()
{
int T,T2 ;
int *nwS, *nwO, *we ;
int *tPoidFutur, *tPoidEtat ;
int *tCod, *bestCod ;
int bestCost, cost, cost2 ;
p_groupe listState ;
int selectLabel ;
int *givTabCod() ;
int *makeTabCode(), *tryAll() ;
int i,j,plusMoins ;
 
if(autoSys->numberState <= 4)
	bestCod = tryAll() ;
else
{
T2 = (autoSys->numberState / 10) + 5 ;

asp(0,0) ;
nwS=(int*)mbkalloc((autoSys->numberState +1)*(autoSys->numberState +1)*sizeof(int)) ;
nwO=(int*)mbkalloc((autoSys->numberState +1)*(autoSys->numberState +1)*sizeof(int ));

mustPoids(nwS,nwO);
we = mustCalcul(nwS,nwO);
tPoidFutur = PoidsFutur();
tPoidEtat = asp_poidEtat();

bestCost = constructBehGivCost(1) ;
bestCod = givTabCod() ;
tCod = makeTabCode(bestCod) ;
bestCod = givTabCod() ;
cost2 = bestCost + 1 ;

if(syf_trace)
	printf("---->initial cost : %d\n",bestCost) ;

listState = stateGeneration();

for(j = 0; j < 2; j++)
	{
	initCode() ;
	switch(j)
		{
		case 0 :
			asp(0,0) ;
			break ;
		case 1 :
			mustJedi() ;
			break ;
		}
	tCod = makeTabCode(tCod) ;
	plusMoins = 1 ;
  while(plusMoins)
	{
	T = 3 ;
	if(NUMBER_CODE(autoSys->numberState) <= T)
		T = NUMBER_CODE(autoSys->numberState) - 1 ;
	while(T)
		{
		write(1,"|",1) ;
		for(i = 0; i<T2; i++)
			{
			listState = stateGeneration();
			while(listState)/* autoSys->cod est affecte automatiquement */
				{	/* tabCod est mis a jour automatiquement */
			   selectLabel=codeModification(we,tPoidEtat,tPoidFutur,tCod,listState);
				listState = delFromgroup(listState,selectLabel);
				}
			fprintf(stdout,".") ;
			fflush(stdout) ;
			cost = constructBehGivCost(1) ;
			if(cost < bestCost)
				{
				bestCost = cost ;
				bestCod = givTabCod() ;
				if(syf_trace)
					printf("---->Best Cost : %d\n",bestCost) ; 
				}
			if(cost2 == cost)
				break ;
			cost2 = cost ;
			}
		printf("\n") ;
		  if(plusMoins == 1)
		  	permutCodPlus(T) ;
		  else
		  	permutCodMoins(T) ;
		/*melangeCod(T) ;*/
		tCod = makeTabCode(tCod) ; /*et non pas giveTabCode*/
		T-- ;
		}
	  plusMoins-- ; 
	  }
	}
tab2Cod(bestCod) ;
postRecuit() ;
}
tab2Cod(bestCod) ;
mbkfree(nwS) ;
mbkfree(nwO) ;
}
/*---------------------------------------------------------------------------
tryAll		: procede a un codage exhaustif et choisit le meilleur selon une
			  fonction de cout.
----------------------------------------------------
parametres	:
----------------------------------------------------
return		: tabCod.
-----------------------------------------------------------------------------*/
int *tryAll()
{
chain_list *lState, *lCode, *lCode1, *lCode2 ;
int bestCost ;
int *bestCod, *tabCod ;
int i,numberCod ;
void orderCod() ;
chain_list *copyChain(), *delChainData() ;

lState = NULL ;
lCode = NULL ;
orderCod(&lState,&lCode) ;
bestCod = givTabCod() ;
tabCod = givTabCod() ;
numberCod = NUMBER_CODE(autoSys->numberState) ;

bestCost = 99999 ;
lCode1 = copyChain(lCode) ;
lCode2 = copyChain(lCode) ;
for(i = 0; i < numberCod; i++)
	{
	freechain(lCode2) ;
	lCode2 = copyChain(lCode1) ;
	affectCod(numberCod - 1, numberCod -1 -i,tabCod,delChainData(lCode2,numberCod -1 -i),&bestCost,&bestCod) ;
	lCode = lCode->NEXT ;
	resetBdd() ;
	}
return(bestCod) ;
}
/*---------------------------------------------------------------------------
AffectCod		: Affecte de maniere recursive tous les codes disponibles a
				  tous les etats de la table des code.
----------------------------------------------------
parametres	: n : le rang de tabCod a affecter.
			  code : code de n eme element : tabCod[n].
			  tabCod : table des codes a remplir.
			  lCod : list des codes disponibles.
			  bestCost : Le cout du meilleur codage.
			  bestCod : table des codes ayant le meilleur code.
----------------------------------------------------
return		: .
-----------------------------------------------------------------------------*/
affectCod(n, code, tabCod, lCod, bestCost, bestCod)
int n, code ;
int *tabCod ;
chain_list *lCod ;
int *bestCost ;
int **bestCod ;
{
int i, cost ;
chain_list *lCod2, *lCod3, *lCod4,*exlCod, *exlCod2 ;
void displayChainInt() ;
chain_list *copyChain(), *delChainData() ;

tabCod[n] = code ;

if(n == 0)
	{
	tab2Cod(tabCod) ;
	cost = constructBehGivCost(1) ;
	if(cost < *bestCost)
		{
		*bestCost = cost ;
		*bestCod = givTabCod() ;
		if(syf_trace)
			printf("---->Best Cost : %d\n",*bestCost) ;
		}
	}
else
	{
	exlCod = copyChain(lCod) ;
	exlCod2 = copyChain(lCod) ;

	while(lCod)
		{
		freechain(exlCod2) ;
		exlCod2 = copyChain(exlCod) ;
		lCod2 = delChainData(exlCod2,lCod->DATA) ;
		affectCod(n-1, lCod->DATA,tabCod,lCod2,bestCost,bestCod) ;
		lCod = lCod->NEXT ;
		}
	}
}
/*---------------------------------------------------------------------------
postRecuit	: Un traitement post-recuit-simule, tentant d'ameliorer le cout
			  localement.
----------------------------------------------------
parametres	:
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
postRecuit()
{
int T ;
int *tCod, *bestCod ;
int bestCost, cost ;
int *givTabCod() ;
int *makeTabCode(), *tryAll() ;
int i, progress, count ;
 
bestCost = constructBehGivCost(1) ;
bestCod = givTabCod() ;
tCod = makeTabCode(bestCod) ;
bestCod = givTabCod() ;

if(syf_trace)
	printf("---->initial cost : %d\n",bestCost) ;

count = 0 ;
progress = 1 ;
T = autoSys->numberState ;
if(T > 32)
	T = T/8 ;
while(progress)
  {
progress = 0 ;
for(i = 0; i < T && count < T; i++)
	{
	count++ ;
	(autoSys->code + tCod[i])->code = i + 1;
	(autoSys->code + tCod[i + 1])->code = i;
	printf(".") ;
	fflush(stdout) ;
	cost = constructBehGivCost(1) ;
	if(cost < bestCost)
		{
		count = 0 ;
		progress = 1 ;
		bestCost = cost ;
		bestCod = givTabCod() ;
		tab2Cod(bestCod) ;
		/*if(syf_trace)*/
		}
	tab2Cod(bestCod) ;
	tCod = makeTabCode(tCod) ; /*et non pas giveTabCode*/
  	}
  }
}
/*---------------------------------------------------------------------------
permutCodPlus	: permute le codage un nbre fini de fois = T.
----------------------------------------------------
parametres	: T.
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
permutCodPlus(T)
int T ;
{
pCode cod ;
int i, num ;

num = NUMBER_CODE(autoSys->numberState) ;
if(T >= num)
	{
	printf("SYF : number of permutation > number of code\n") ;
	exit(-1) ;
	}

cod = autoSys->code ;
for(i = 0; i < num; i++)
	{
	cod->code = cod->code + T ;

	if(cod->code >= num)
		cod->code = cod->code - num ;
	cod++ ;
	}
}
/*---------------------------------------------------------------------------
permutCodMoins	: permute le codage un nbre fini de fois = T.
----------------------------------------------------
parametres	: T.
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
permutCodMoins(T)
int T ;
{
pCode cod ;
int i, num ;

num = NUMBER_CODE(autoSys->numberState) ;
if(T >= num)
	{
	printf("SYF : number of permutation > number of code\n") ;
	exit(-1) ;
	}

cod = autoSys->code ;
for(i = 0; i < num; i++)
	{
	cod->code = cod->code - T ;

	if(cod->code < 0)
		cod->code = cod->code + num ;
	cod++ ;
	}
}
/*---------------------------------------------------------------------------
tab2Cod		: remplit autoSys->code a partir d'une table de codes.
----------------------------------------------------
parametres	: table des codes.
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
tab2Cod(tab)
int *tab ;
{
int i ;
int num ;

num =  NUMBER_CODE(autoSys->numberState);

for(i = 0; i < num; i++)
	(autoSys->code + i)->code = tab[i] ;
}
/*---------------------------------------------------------------------------
melangeCod	: melange le codage plus ou moin en fonction de T.
----------------------------------------------------
parametres	: T.
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
melangeCod(T)
int T ;
{
int *rand ;
int i, num, cod ;

num = (NUMBER_BIT(autoSys->numberState) + T) % (NUMBER_CODE(autoSys->numberState)) -1 ;
rand = (int *)mbkalloc(num* sizeof(int)) ;

for(i = 0; i < num; i++)
	{
	/*rand[i] = ((int)random() % T) % (num - i) ;*/
	rand[i] = num - i ;
	}

for(i = 0; i < num; i++)
	{
	cod = (autoSys->code + i)->code ;
	/*printf("code[%d] = %d\n",i,(autoSys->code + i)->code) ;
	printf("code[%d] = %d\n",rand[i],(autoSys->code + rand[i])->code) ;*/
	(autoSys->code + i)->code = (autoSys->code + rand[i])->code ;
	(autoSys->code + rand[i])->code = cod ;
	/*printf("code[%d] = %d\n",i,(autoSys->code + i)->code) ;
	printf("code[%d] = %d\n",rand[i],(autoSys->code + rand[i])->code) ;*/
	}
}
/*---------------------------------------------------------------------------
initCode	: remet a '0' tous les codes.
----------------------------------------------------
parametres	: .
----------------------------------------------------
return		: .
-----------------------------------------------------------------------------*/
initCode()
{
int i ;

for(i = 0; i< autoSys->numberState; i++)
	(autoSys->code + i)->code = 0 ;
}
/*---------------------------------------------------------------------------
orderCod	: Fait un codage ordonne'. 0<-->e0, 1<-->e1 .....
----------------------------------------------------
parametres	: list des labels d'etats a remplir.
			  list des codes d'etats a remplir.
----------------------------------------------------
return		: rien.
-----------------------------------------------------------------------------*/
void orderCod(lState,lCode)
chain_list **lState, **lCode ;
{
int i ;

for(i = 0; i < NUMBER_CODE(autoSys->numberState); i++)
	{
	(autoSys->code + i)->code = i ;
	*lState = addchain(*lState,i) ;
	*lCode = addchain(*lCode,i) ;
	}
}
/*---------------------------------------------------------------------------
copyChain	: Renvoie une chain_list correspondant au copy de celle passee en
			  parametre.
----------------------------------------------------
parametres	: list.
----------------------------------------------------
return		: nouvelle list.
-----------------------------------------------------------------------------*/
chain_list *copyChain(list)
chain_list *list ;
{
chain_list *list2 ;

list2 = NULL ;
while(list)
	{
	list2 = addchain(list2,list->DATA) ;
	list = list->NEXT ;
	}
return(list2) ;
}
/*---------------------------------------------------------------------------
delChainData: elimine l'element de la chaine list contenant le data passe en
			  param. Si l'element nexiste pas retourne la list elle meme.
----------------------------------------------------
parametres	: list. data
----------------------------------------------------
return		: nouvelle list.
-----------------------------------------------------------------------------*/
chain_list *delChainData(list,data)
chain_list *list ;
void *data ;
{
chain_list *list2 ;

list2 = list ;
while(list)
	{
	if(list->DATA == data)
		{
		list2 = delchain(list2,list) ;
		return(list2) ;
		}
	list = list->NEXT ;
	}
return(list2) ;
}
