N pistas: Velocidade média em função da densidade e fluxo em função da densidade

De Física Computacional
Ir para navegação Ir para pesquisar
#include<stdio.h>
#include<stdlib.h>
#include<math.h> 


/* declaracao de funcoes */
void passo(void);
void inicializacao(void);
void atualizar_posicao(void);
int mudar_velocidade(int(v));
int calculo_distancia(void);
int trocar_faixa(void);


/*  declaracao var global   */
#define tempo_max 100
#define comprimento_rua 100
#define num_faixas 2
#define veloc_max 6


/*  velocidade: numero de posições   */
/*  que o carro andará num passo     */

//precisamos guardar as posicoes anteriores, por isso rua e rua_nova
//definimos vel[comprimento_rua*num_faixas], pois o numero maximo de carros = comprimento_rua*num_faixas
int rua[num_faixas][comprimento_rua], rua_nova[num_faixas][comprimento_rua], vel[comprimento_rua*num_faixas];

int prim_carro[num_faixas], dist[num_faixas], num_carros;
int i, j, k, t, ultimo, k_novo, faz_nada;

//z_max = numero de amostragens
int z, z_max = 100000;

//probab_vel = probabilidade de reducao da velocidade
double probab_vel = 0.3;

//print: precisamos primeiro coletar todos os resultados, fazermos a media, para so entao printarmos
//print[0][i] guarda a velocidade media
//print[1][i] guarda o fluxo
double v_media, fluxo, print[2][num_faixas*comprimento_rua];

void main(void)
{
	
	FILE *vm;
	char arq[30];
	sprintf(arq, "%d_lanes_dens.dat", num_faixas);
	vm = fopen(arq, "w+");	

	double v_media;
    
    for(num_carros = 1; num_carros < num_faixas*comprimento_rua; num_carros++)
    {
    	print[0][num_carros] = 0;
    	print[1][num_carros] = 0;
    }
	
	for(z = 0; z < z_max; z++)
	{
		for(num_carros = 1; num_carros < num_faixas*comprimento_rua; num_carros++)
		{
	
	
			v_media = 0;
			fluxo = 0;
			
			inicializacao();
			for(t = 0; t < tempo_max; t++)
			{	
				
				passo();
		
			}
			
			//fluxo = numero de carros/(area*tempo)
			//area da secao transversal dada pelo numero de faixas
			fluxo /= (tempo_max*num_faixas);
			
			//calculo da velocidade media
			for(k = 0; k < num_carros; k++)
			{
				v_media += vel[k];
			}
			v_media /= num_carros;
			
			print[0][num_carros] += v_media;
			print[1][num_carros] += fluxo;
		}
	}
	
	for(num_carros = 1; num_carros < num_faixas*comprimento_rua; num_carros++)
    {
    	fprintf(vm, "%lf %lf %lf\n", ((double)num_carros)/(num_faixas*comprimento_rua), print[0][num_carros]/z_max, print[1][num_carros]/z_max);
    }

	
	fclose(vm);
}



void inicializacao(void){

	//srand48(time(NULL));

   	// zerando vetores
   	//-1 significa que a posicao esta vazia
   	
	for(i = 0; i < comprimento_rua; i++){

		for(j = 0; j < num_faixas; j++){

			rua[j][i] = -1;
			rua_nova[j][i] = rua[j][i];
			
		}
	}
	
	//iniciando os carros - rua[k][i] representa o indice do carro, atraves do qual acessaremos sua velocidade em vel[rua[k][i]]
	//da forma como fazemos aqui, iniciamos os carros distribuidos em todas as pistas e equidistantes (aproximadamente)
	k = 0;
	for(i = 0; (i < num_carros) && (k < num_faixas); i++)
	{
		
		vel[i] = 0;	
		
		
		rua[k][(i*comprimento_rua*num_faixas/num_carros) % comprimento_rua] = i;
		rua_nova[k][(i*comprimento_rua*num_faixas/num_carros) % comprimento_rua] = i;
		
		//para trocar de faixa quando a condicao for satisfeita
		if((i+1)*comprimento_rua*num_faixas/num_carros >= comprimento_rua* (k + 1))
		{
			k++;
		}
	}
		
}



void passo(void)
{
	
	//atualizando a matriz rua, trocando -2 por -1
	for(k = 0; k < num_faixas; k++)
	{
		for(i = 0; i< comprimento_rua; i++)
		{
			if(rua_nova[k][i] == -2)
			{
				rua_nova[k][i] = -1;
			}
			
			rua[k][i] = rua_nova[k][i];
		}
		
		//para que caso ainda nao haja um primeiro carro, prim_carro assuma um valor que nao se confunda com nenhum indice de carro (que vao de 0 a num_carros)
		prim_carro[k] = -1;
	}
	
	//iterando pela avenida, fixando a posicao ao longo da avenida e variando as pistas
	for(i = 0; i< comprimento_rua; i++)
	{
		
		//calculando a distancia a partir daquela posicao ate o proximo carro, para todas as pistas
		for(k = 0; k < num_faixas; k++)
		{
			dist[k] = calculo_distancia();
		}
		
		
    	for(k = 0; k < num_faixas; k++)
  		{
  			//precisamos de k_novo, ja que o carro pode trocar de pista, mudando seu k
			k_novo = k;
			
			if (rua[k][i] != -1){
			
	
				/*	caso for o primeiro carro,	*/
				/*	salvar sua posicao para    	*/
				/*	calcularmos a distancia do 	*/
				/*	ultimo carro ao primeiro   	*/

				if(prim_carro[k] == -1){

					prim_carro[k] = i;
				}

				//mudando velocidades
				vel[rua[k][i]] = mudar_velocidade(vel[rua[k][i]]);
				
				/*	           Regra 3              */
				/*	redução de velocidade randomica	*/

				/* fazemos isso aqui por causa da possibilidade de troca de pista: */
				/* ao trocar de pista, o carro vai ter sua velocidade verificada e */
				/* modificada novamente - se a regra 3 estivesse dentro da funcao  */
				/* mudar_velocidade, ela seria aplicada duas vezes nesse caso 	   */

				if( ( vel[rua[k][i]] > 0 ) && ( drand48() < probab_vel )){

					vel[rua[k][i]]--;
				}
							
				//atualizando posicoes
				atualizar_posicao();

			}	
		}
	}
	
}




void atualizar_posicao(void){

	/*	atualiza apenas se a velocidade	*/
	/*	for diferente de zero        	*/
	if(vel[rua[k][i]] != 0){

		//se for o ultimo carro, usamos condicoes de contorno periodicas
		if( i + vel[rua[k][i]] >= comprimento_rua ){

			//como somente os carros que atravessam a secao transversal entre a ultima e a primeira celula da rua entram nesse if, podemos contar o fluxo aqui
			fluxo++;

			rua_nova[k_novo][(i+ vel[rua[k][i]]) % comprimento_rua] = rua[k][i];
			
			j = i+1;
			while(j < (i+ vel[rua[k][i]]) % comprimento_rua)
			{
				/* -2 indica o caminho percorrido por um carro (para que nenhum */
				/* outro consiga trocar de pista para essa posicao)				*/	
				rua_nova[k_novo][j] = - 2;

				/* caso estejamos na ultima celula, se fizermos j = -1, */ 
				/* no proximo passo j = 0 e voltaremos ao inicio da rua */
				if(j==comprimento_rua - 1)
				{
					j = -1;
				}
				
				j++;
			}
		}
		else{

			rua_nova[k_novo][i + vel[rua[k][i]]] = rua[k][i];
			for(j = i + 1; j < i + vel[rua[k][i]]; j++)
			{
				rua_nova[k_novo][j] = -2;
			}
			
		}
		//-2 indica que havia um carro ali	
		rua_nova[k][i] = -2;
	}
	
	/* caso v=0. mas troque de pista, (ja que pode ser que o carro */
	/* troque de pista com v=1, mas tenha sua velocidade diminuida */
	/* para 0 por causa da Regra 3)								   */
	else if((vel[rua[k][i]] == 0) && (k != k_novo))
	{
		rua_nova[k_novo][i] = rua[k][i];
		rua_nova[k][i] = -2;
	}
				
}




int calculo_distancia(void){

		int x;
		/*	RETORNA A DISTANCIA ENTRE O	*/
		/*	CARRO 'i' E O QUE ESTA NA   */
		/*	SUA FRENTE NA FAIXA 'x'    	*/ 

		/*	caso não for o ultimo carro	*/
		/*	procura posição do prox. e	*/
		/*	calcula a distancia até ele	*/

		/* temos que isolar o caso i = comprimento_rua - 1,*/
		/*	já que j = i + 1 = comprimento_rua, e usamos   */
		/*	rua[j][k], sendo que j < comprimento_rua	   */
		/*												   */
		/*	se i = comprimento_rua - 1, j = comprimento_rua*/
		/*	e j deve ser < comprimento_rua				   */

		ultimo = 0;
		
		if( i + 1 < comprimento_rua )
		{

			j = i + 1;

			while ( rua[k][j] == -1 ){

				if( j == comprimento_rua - 1 ){
					ultimo = 1;
					break;
				}
				j++;	
			}
		
			if ( ultimo == 0 ){

				x = j - i;
			}
			
		}

			/*	para o ultimo carro a distan-	*/
			/*	cia é calculada em relacao ao	*/
			/*	primeiro, pois são C.C. perio-	*/
			/*	dicas.                       	*/
			//aqui devemos tomar cuidado, pois caso a pista esteja vazia, 
			//ultimo = 1, mas nao existe prim_carro[k]. Por isso 
			//definimos prim_carro[k] inicialmente como -1
			
		else if(i == comprimento_rua - 1)
		{
			ultimo = 1;
		}
		
		//ultimo carro, e existe um primeiro carro (numero de carros > 1)
		if((ultimo == 1) && (prim_carro[k] != -1)){

			x = comprimento_rua - (i - prim_carro[k]);
		}
		
		//caso a pista esteja vazia	ou numero de carros = 1
		else if((ultimo == 1) && (prim_carro[k] == -1))
		{
			x = comprimento_rua;
		}	

		return x;

}




int mudar_velocidade(int(v)){

	int x;
	/*   	RETORNA NOVA VELOCIDADE  	*/	

	/*	            Regra 1         	*/
	/*	caso dê pra acelerar, acelere	*/
	if( ( v < veloc_max ) && ( dist[k_novo] > v + 1 ) ){

		x = v + 1;
	}

	/*	           Regra 2           	*/
	/*	caso pouco espaço, desacelere	*/
	else if( dist[k_novo] < v + 1 ){
		
		//indica se a verificacao de troca de pista resultou em algo
		faz_nada = 0;
		
		//para garantir que um carro que ja trocou de faixa nao entre aqui
		if(k == k_novo)
		{
			//verificacao para trocar de faixa
			x = trocar_faixa();
		}
		//caso o carro ja tenha trocado de faixa
		else
		{
			x = dist[k_novo] - 1;
		}
		
		//se nao deu pra trocar de faixa
		if(faz_nada == 1)
		{
			x = dist[k_novo] - 1;
		}
	}
	
	
	/*Caso em que v=dist-1, ou seja, nao se alteraria*/
	else if((dist[k_novo] == v + 1) && (v != veloc_max))
	{
		faz_nada = 0;
		
		//para garantir que um carro que ja trocou de faixa nao entre aqui
		if(k == k_novo)
		{
			x = trocar_faixa();
		}
		//caso o carro ja tenha trocado de faixa
		else
		{
			x = v;
		}
		
		//se nao deu pra trocar de faixa ou se o carro ja trocou de faixa
		if(faz_nada == 1)
		{
			x = v;
		}
	}
	else
	{
		x = v;
	}
	
	return x;
}


int trocar_faixa(void)
{
	int y;
	//verificacao para trocar de faixa	
	
	//tem duas pistas de cada lado
	if((k_novo - 1 >= 0) && (k_novo + 1 < num_faixas))
	{
		//ambas vazias
		if((rua_nova[k_novo-1][i] == -1) && (rua_nova[k_novo+1][i] == -1))
		{
		
			//ambas com mais espaço
			if((dist[k_novo-1] > dist[k_novo]) && (dist[k_novo+1] > dist[k_novo]))
			{
				if(dist[k_novo-1] > dist[k_novo+1])
				{
					k_novo--;
				}
				else if(dist[k_novo+1] > dist[k_novo-1])
				{
					k_novo++;
				}
				//caso dist[k+1]=dist[k-1], escolha aleatoria
				else if(drand48() < 0.5)
				{
					k_novo--;
				}
				else
				{
					k_novo++;
				}
				
				y = mudar_velocidade(vel[rua[k][i]]);
			}
			//so o lado k-1 com mais espaco
			else if(dist[k_novo-1] > dist[k_novo])
			{
				k_novo--;
				
				y = mudar_velocidade(vel[rua[k][i]]);
			}
			//so o lado k+1 com mais espaco
			else if(dist[k_novo+1] > dist[k_novo])
			{
				k_novo++;
				
				y = mudar_velocidade(vel[rua[k][i]]);
			}
			//nenhuma com espaco
			else
			{
				faz_nada = 1;
			}
		}
		//so o lado k-1 vazio
		else if((rua_nova[k_novo-1][i] == -1) && (dist[k_novo-1] > dist[k_novo]))
		{
			k_novo--;
			
			y = mudar_velocidade(vel[rua[k][i]]);
		}
		//so o lado k+1 vazio
		else if((rua_nova[k_novo+1][i] == -1) && (dist[k_novo+1] > dist[k_novo]))
		{
			k_novo++;
		
			y = mudar_velocidade(vel[rua[k][i]]);
		}
		//nenhum lado vazio
		else
		{
			faz_nada = 1;
		}
	}
	//so pista do lado k-1
	else if(k_novo - 1 >= 0)
	{
		//se esta vazia e se ha mais espaco
		if((rua_nova[k_novo-1][i] == -1) && (dist[k_novo-1] > dist[k_novo]))
		{
			k_novo--;
			
			y = mudar_velocidade(vel[rua[k][i]]);
		}
		//nao esta vazia/ sem espaco
		else
		{
			faz_nada = 1;
		}
	}
	//so pista do lado k+1
	else if(k_novo + 1 < comprimento_rua)
	{
		//se esta vazia e se ha mais espaco
		if((rua_nova[k_novo+1][i] == -1) && (dist[k_novo+1] > dist[k_novo]))
		{
			k_novo++;
			
			y = mudar_velocidade(vel[rua[k][i]]);
		}
		//nao esta vazia/sem espaco
		else
		{
			faz_nada = 1;
		}
	}
	else
	{
		faz_nada = 1;
	}
	
	return y;
}