N pistas: Velocidade média em função do tempo
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 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;
}