forked from piLaboratory/TWoLife
-
Notifications
You must be signed in to change notification settings - Fork 0
/
individuo.cpp
228 lines (200 loc) · 6.75 KB
/
individuo.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include "individuo.hpp"
#include <cmath>
#include "paisagem.hpp"
#include <cstdlib>
#include <iostream>
#include <R.h>
#include <Rmath.h>
using namespace std;
unsigned long individuo::MAXID = 0;
/** \brief Exceção no indivíduo.
*
* Esta classe implementa uma exceção ocorrida na classe indivíduo. Atualmente, é usada para detectar valores impossíveis
* passados no construtor, mas vai ser expandida para compreender mais casos (\ref TBI). */
class individuo_exception: public exception
{
virtual const char* what() const throw()
{
return "Aconteceu uma exceção na classe indivíduo!";
}
} myex;
individuo::individuo(double x, double y, int especie, double taxa_morte,
double orientacao, double angulo_visada,
double passo, double move, double raio,
double taxa_basal, int semente, //retirar int semente
double incl_b, double incl_d,
double death_mat, int dens_type):
id(++MAXID), // pega o próximo ID livre
x(x),
y(y),
especie(especie),
taxa_morte(taxa_morte),
move(move),
passo(passo),
orientacao(orientacao),
ang_visada(angulo_visada),
raio(raio),
taxa_basal(taxa_basal),
semente(semente),
incl_birth(incl_b),
incl_death(incl_d),
const_d_matrix(death_mat),
dens_type(dens_type)
{
if (taxa_morte < 0) throw myex;
if (passo < 0) throw myex;
if (move < 0) throw myex;
if (raio < 0) throw myex;
if (taxa_basal < 0) throw myex;
if(incl_birth!=0 && incl_death!=0)
{
this->densi_max = (taxa_basal-taxa_morte)/(incl_b+incl_d);
this->birth_death_eq = taxa_morte+incl_d*((taxa_basal-taxa_morte)/(incl_b+incl_d));
}
//cout << this->raio << endl;
}
/** \brief função para reprodução assexuada de um indivíduo
*
* Faz uma cópia do indivíduo pai. Recebe um ponteiro dereferenciado (nomeado rhs) e usa isto para
* Criar novo individuo com os mesmos valores de atributo do pai, exceto
* - id (veja \ref individuo::get_id)
* - vizinhos (veja \ref individuo::set_vizinhos) &&&&&&&& mudou já que os individuos nascem no mesmo local do pai
* - tempo para evento (veja \ref individuo::get_tempo)
* Usa notacao :atributo(valor) ao inves de atribuicão.
* Funcao chamada por paisagem::realiza_acao() quando a ação é um nascimentto
* @param rhs ponteiro dereferenciado para o pai */
individuo::individuo(const individuo& rhs)
:id(++MAXID),
x(rhs.x),
y(rhs.y),
especie(rhs.especie),
taxa_morte(rhs.taxa_morte),
move(rhs.move),
passo(rhs.passo),
ang_visada(rhs.ang_visada),
raio(rhs.raio),
taxa_basal(rhs.taxa_basal),
tipo_habitat(rhs.tipo_habitat),
semente(rhs.semente),
incl_birth(rhs.incl_birth),
incl_death(rhs.incl_death),
const_d_matrix(rhs.const_d_matrix),
dens_type(rhs.dens_type),
birth_death_eq(rhs.birth_death_eq),
lisViz(rhs.lisViz)
{ //precisamos dessa chave e da que fecha ela?
}
/** \brief Método de atualização dos indivíduos
* Esta função é a camada de atualização dos indivíduos
* A cada execução deste método:
* - É atualizada a taxa de nascimento de acordo com a densidade de vizinhos no raio de vizinhanca obtido com paisagem::atualiza_vizinhos
* - Sorteia o tempo de acordo com as novas taxas
* As taxas de morte e movimentação no momento fixas. Mas tambem serão funções da densidade de vizinhos (\ref TBI).
*/
////////////////////////////// UPDATES /////////////////////////////////////////////////////
void individuo::updateEXPi()
{
this->birth = this->taxa_basal;
this->death = this->taxa_morte;
this->sampleTimeEXP();
}
void individuo::updateLOGi(double dens)
{
double densi = dens; // densidade inclui n de vizinhos + o individuo
this->birth = this->taxa_basal-this->incl_birth*densi;
this->death = this->taxa_morte+this->incl_death*densi;
if(this->birth<0){this->birth=0;}
this->sorteiaTempo();
}
void individuo::updateRWi()
{
/*
if(this->tipo_habitat==0)
{
this->move = ?????????????; GENERALIZAR MOVIMENTAÇÃO PELA MATRIZ
}
else
*/
this->sampleTimeRW();
}
void individuo::updateSKEXPi()
{
if(this->tipo_habitat==0)
{
this->birth = 0;
// ToDo: Implementar aqui modelo mais geral para mortalidade na matriz. Aqui a denso dependencia é igual à do habitat, só muda a mortalidade basal que é maior que no habitat.
this->death = this->const_d_matrix*this->taxa_morte;
}
else
{
this->birth = this->taxa_basal;
this->death = this->taxa_morte;
}
this->sorteiaTempo();
}
void individuo::updateSKLOGi(double dens)
{
double densi = dens; // densidade inclui n de vizinhos + o individuo
if(this->tipo_habitat==0)
{
this->birth = 0;
// ToDo: Implementar aqui modelo mais geral para mortalidade na matriz. Aqui a denso dependencia é igual à do habitat, só muda a mortalidade basal que é maior que no habitat.
this->death = this->const_d_matrix*this->taxa_morte+this->incl_death*densi;
}
else
{
this->birth = this->taxa_basal-this->incl_birth*densi;
this->death = this->taxa_morte+this->incl_death*densi;
}
if(this->birth<0){this->birth=0;}
this->sorteiaTempo();
}
////////////////////// SAMPLING TIME METHODS /////////////////////////////////////////
void individuo::sorteiaTempo()
{
this->tempo_evento = rexp(1.0/(this->move+this->birth+this->death));
}
void individuo::sampleTimeEXP()
{
this->tempo_evento = rexp(1.0/(this->taxa_basal+this->taxa_morte));
}
void individuo::sampleTimeRW()
{
this->tempo_evento = rexp(1.0/(this->move));
}
////////////////
int individuo::sorteia_acao()
{
vector<double> probscum;
double total = this->death+this->birth+this->move;
probscum.push_back(this->death/total);
probscum.push_back(probscum[0]+(this->birth/total));
probscum.push_back(probscum[1]+(this->move/total));
double evento;
evento = runif(0.0,1.0);
int decisao;
for(unsigned int i=0; i<probscum.size()-1; i++)
{
if(probscum[i]>evento)//encontrar o primeiro maior valor
{
decisao = i;
return decisao;//retorna a decisao tomada para o mundo (0 = morte, 1 = nascer, 2 = andar)
break;
}
}
return probscum.size()-1;
}
void individuo::anda(bool aleatorio)
{
//a cada movimentacao ele muda de direcao; random walk dentro de um angulo de visao
if (aleatorio) {
this->orientacao = runif(-180.0,180.0);//random way point para sortear uma direcao qualquer
} else {
this->orientacao+= runif(-ang_visada/2.0, ang_visada/2.0);//random way point
}
double oriRad=this->orientacao*M_PI/180.0;//tranforma em radianos para poder calcular as distancias das posicoes x e y
double dx= cos(oriRad)*this->passo;
double dy= sin(oriRad)*this->passo;
this->x+=dx;
this->y+=dy;
}