N pistas: Velocidade média em função do tempo: mudanças entre as edições

De Física Computacional
Ir para navegação Ir para pesquisar
Sem resumo de edição
Sem resumo de edição
 
(Uma revisão intermediária pelo mesmo usuário não está sendo mostrada)
Linha 46: Linha 46:
FILE *vm;
FILE *vm;
char arq[30];
char arq[30];
sprintf(arq, "n_lanes_v_med_t_dens_0%.0lf.dat", 10*((double)num_carros)/(num_faixas*comprimento_rua));
sprintf(arq, "%d_lanes_v_med_t_dens_0%.0lf.dat", num_faixas, 10*((double)num_carros)/(num_faixas*comprimento_rua));
vm = fopen(arq, "w+");
vm = fopen(arq, "w+");
Linha 105: Linha 105:
}
}
//iniciando os carros - rua[i] representa o indice do carro, atraves do qual acessaremos sua velocidade em vel[rua[i]]
//iniciando os carros - ru[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)
//da forma como fazemos aqui, iniciamos os carros distribuidos em todas as pistas e equidistantes (aproximadamente)
k = 0;
k = 0;

Edição atual tal como às 16h49min de 24 de janeiro de 2018

#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 num_carros 60
#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
int rua[num_faixas][comprimento_rua], rua_nova[num_faixas][comprimento_rua], vel[num_carros];

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

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

//probab_vel = probabilidade de reduzir a velocidade
double probab_vel = 0.3;

//print: precisamos primeiro coletar todos os resultados, fazermos a media, para so entao printarmos
double v_media, print[tempo_max];


void main(void)
{
	
	FILE *vm;
	char arq[30];
	sprintf(arq, "%d_lanes_v_med_t_dens_0%.0lf.dat", num_faixas, 10*((double)num_carros)/(num_faixas*comprimento_rua));
	vm = fopen(arq, "w+");
	
	double v_media;
    
    for(t = 0; t < tempo_max; t++)
    {
    	print[t] = 0;
    }
	
	for(z = 0; z < z_max; z++)
	{
		inicializacao();
		for(t = 0; t < tempo_max; t++)
		{	
			v_media = 0;
		
			//calculo da velocidade media ao longo do tempo
			for(k = 0; k < num_carros; k++)
			{
				v_media += vel[k];
			}
			v_media /= num_carros;
			
			print[t] += v_media;
			
			passo();
					
		}
	}
	
	for(t = 0; t < tempo_max; t++)
    {
    	fprintf(vm, "%d %lf\n", t, print[t]/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 - ru[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 ){

			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;
}