TProcura
Biblioteca em C++ para testes paramétricos de algoritmos, e coleção de algoritmos de procura e otimização
Loading...
Searching...
No Matches
TCodificacaoPermutacao.cpp
Go to the documentation of this file.
2
3int TCodificacaoPermutacao::nElementos = 0; // número de elementos na permutação
4const char* TCodificacaoPermutacao::nomesVizinhanca[] = {
5 "inserir",
6 "trocaPar",
7 "inverterSegmento" };
8
13
16 for (int i = 0; i < nElementos; i++)
17 estado[i] = i;
19 custo = -1;
20}
21
22void TCodificacaoPermutacao::Debug(bool completo) {
23 for (int i = 0; i < nElementos; i++)
24 printf("%d ", estado[i]);
25}
26
28 static const char* nomesCruzamento[] = {
29 "PMX",
30 "Edge",
31 "Order",
32 "Cycle"};
33 static const char* nomesDistancias[] = {
34 "Hamming", // número de posições com valores diferentes
35 "Kendall tau", // número de pares fora de ordem
36 "Spearman footrule" }; // soma das diferenças absolutas das posições
37
39
40 // parametros da codificação inteira
41 parametro += {
42 { "TIPO_CRUZAR", 3, 1, 4, "TIPO_CRUZAR: 1 - PMX, 2 - Edge, 3 - Order; 4 - Cycle", nomesCruzamento, _TV("0,2,3") },
43 { "TIPO_MUTAR", 0,0,0, "TIPO_MUTAR: 0 - aplica um vizinho aleatório (seja 1 só elemento ou segmento)", NULL, _TV("0,2,3") },
44 { "TIPO_VIZINHO", 1,1,3, "TIPO_VIZINHO: vários métodso para vizinhanças de inteiros", nomesVizinhanca, _TV("0,1") },
45 { "LIMITE_VIZINHOS", 0,0,1000,
46"LIMITE_VIZINHOS, conforme a vizinhança, se 0 não há limite\n\
47- inserir + trocaPar + inverterSegmento - limita a distância entre pares" },
48 { "TIPO_DISTANCIA", 1,1,3, "Distância: vários métodso para distâncias de permutações", nomesDistancias, _TV("0,2,3") }
49 };
50}
51
55 auto& A = ((TCodificacaoPermutacao*)a)->estado;
56 auto& B = ((TCodificacaoPermutacao*)b)->estado;
57
58 estado.Reset(-1);
59
60 // vetor de marcação (usado/copied) disponível para todos os operadores
63 usado.Reset(false);
64
65 // escolher dois pontos de corte distintos
66 while (divisoes.Count() < 2) {
68 divisoes.BeASet();
69 }
70
71 int inicio = divisoes.First();
72 int fim = divisoes.Last();
73
74 if (operador == 1) { // PMX
75 Debug(EXTRA_DEBUG, false, " cruzamento PBX %d - %d", inicio, fim);
76 // mapeamento valor -> posição em B
79 for (int i = 0; i < nElementos; i++)
80 posB[B[i]] = i;
81
82 // copiar segmento de A
83 for (int i = inicio; i <= fim; i++) {
84 estado[i] = A[i];
85 usado[A[i]] = true;
86 }
87
88 // tratar elementos de B no segmento que não foram copiados
89 for (int i = inicio; i <= fim; i++) {
90 int val = B[i];
91 if (!usado[val]) {
92 int pos = i;
93 while (true) {
94 int novoValor = A[pos];
95 int novaPos = posB[novoValor];
96 if (estado[novaPos] < 0) {
98 usado[val] = true;
99 break;
100 }
101 if (pos == novaPos) {
102 if (estado[pos] < 0) {
103 estado[pos] = val;
104 usado[val] = true;
105 }
106 break;
107 }
108 pos = novaPos;
109 }
110 }
111 }
112
113 // preencher restantes posições com elementos de B
114 for (int i = 0; i < nElementos; i++)
115 if (estado[i] < 0)
116 estado[i] = B[i];
117 }
118 else if (operador == 2) { // ERX
120 Debug(EXTRA_DEBUG, false, " cruzamento ERX");
121
122 adj.Count(nElementos);
123
124 auto addEdge = [&](int from, int to) {
125 if (adj[from].Find(to) < 0)
126 adj[from] += to;
127 };
128
129 // adicionar arestas de A
130 for (int i = 0; i < nElementos; i++) {
131 int left = A[(i - 1 + nElementos) % nElementos];
132 int right = A[(i + 1) % nElementos];
133 addEdge(A[i], left);
134 addEdge(A[i], right);
135 }
136 // adicionar arestas de B
137 for (int i = 0; i < nElementos; i++) {
138 int left = B[(i - 1 + nElementos) % nElementos];
139 int right = B[(i + 1) % nElementos];
140 addEdge(B[i], left);
141 addEdge(B[i], right);
142 }
143
145 for (int i = 0; i < nElementos; i++) {
146 estado[i] = current;
147 usado[current] = true;
148
149 // escolher próximo
150 int next = -1;
151 if (!adj[current].Empty()) {
152 int minSize = nElementos + 1;
154 for (int v : adj[current]) {
155 if (!usado[v]) {
156 int size = adj[v].Count();
157 if (size < minSize) {
158 minSize = size;
159 candidatos = {};
160 candidatos += v;
161 }
162 else if (size == minSize) {
163 candidatos += v;
164 }
165 }
166 }
167 if (!candidatos.Empty())
168 next = candidatos.Random();
169 }
170
171 if (next == -1) {
172 for (int v = 0; v < nElementos; v++)
173 if (!usado[v]) { next = v; break; }
174 }
175
176 current = next;
177 }
178 }
179 else if (operador == 3) { // OX
180 Debug(EXTRA_DEBUG,false," cruzamento OX %d - %d", inicio, fim);
181 for (int i = inicio; i <= fim; i++) {
182 estado[i] = A[i];
183 usado[A[i]] = true;
184 }
185
186 int pos = (fim + 1) % nElementos;
187 int idxB = (fim + 1) % nElementos;
188
189 while (pos != inicio) {
190 int val = B[idxB];
191 if (!usado[val]) {
192 estado[pos] = val;
193 usado[val] = true;
194 pos = (pos + 1) % nElementos;
195 }
196 idxB = (idxB + 1) % nElementos;
197 }
198 }
199 else if (operador == 4) { // CX
201 Debug(EXTRA_DEBUG, false, " cruzamento CX");
202 posB.Count(nElementos);
203 for (int i = 0; i < nElementos; i++)
204 posB[B[i]] = i;
205
206 bool fromA = true;
207 int start = 0;
208
209 while (true) {
210 while (start < nElementos && usado[start])
211 start++;
212 if (start >= nElementos)
213 break;
214
215 int pos = start;
216 do {
217 estado[pos] = fromA ? A[pos] : B[pos];
218 usado[pos] = true;
219 int val = fromA ? A[pos] : B[pos];
220 pos = posB[val];
221 } while (pos != start);
222
223 fromA = !fromA;
224 }
225 }
226}
227
229 // inverter segmento de N bits
232 Debug(EXTRA_DEBUG, false, " vizinhança %s (limite %d)",
233 nomesVizinhanca[tipo - 1], limiteVizinhanca);
234 // alterar posição de elementos
235 for (int i = 0; i < nElementos; i++) // elemento i
236 for (int j = 0; j < nElementos; j++) // elemento j ou local j
237 if (i != j && (!limiteVizinhanca || abs(i - j) <= limiteVizinhanca)) {
239 if (vizinho != NULL) {
240 if (tipo == vizInserirCP) {
241 int valor = vizinho->estado[i];
242 for (int k = i; k != j; (i < j ? k++ : k--))
243 vizinho->estado[k] = vizinho->estado[i < j ? k + 1 : k - 1];
244 vizinho->estado[j] = valor;
245 }
246 else if (tipo == vizTrocaParCP && i < j) { // trocaPar
247 int valor = vizinho->estado[i];
248 vizinho->estado[i] = vizinho->estado[j];
249 vizinho->estado[j] = valor;
250 }
251 else if (tipo == vizInverterSegmentoCP && i < j) { // inverterSegmento
252 int ii = i, jj = j;
253 while (ii < jj) {
254 int valor = vizinho->estado[ii];
255 vizinho->estado[ii] = vizinho->estado[jj];
256 vizinho->estado[jj] = valor;
257 ii++;
258 jj--;
259 }
260 }
261
262 vizinho->custo = -1;
263 vizinhos += vizinho;
264 }
265 else
266 memoriaEsgotada = true;
267 }
269}
270
272 // mutação com probabilidade p de trocar cada bit
275 if (p == 0) {
276 // um vizinho aleatório
279 int i = TRand::rand() % nElementos;
280 int j = TRand::rand() % nElementos;
283 Debug(EXTRA_DEBUG, false, " mutar vizinho %s (%d,%d)",
284 nomesVizinhanca[tipo - 1], i, j);
285 if (tipo == vizInserirCP) {
286 int valor = estado[i];
287 for (int k = i; k != j; (i < j ? k++ : k--))
288 estado[k] = estado[i < j ? k + 1 : k - 1];
289 estado[j] = valor;
290 }
291 else if (tipo == vizTrocaParCP) {
292 int valor = estado[i];
293 estado[i] = estado[j];
294 estado[j] = valor;
295 }
296 else if (tipo == vizInverterSegmentoCP) {
297 while (i < j) {
298 int valor = estado[i];
299 estado[i] = estado[j];
300 estado[j] = valor;
301 i++;
302 j--;
303 }
304 }
305 }
306}
307
309 int dist = 0;
313 if (tipo == distKendallTauCP) {
314 // número de pares fora de ordem
315 for(int i=0; i<nElementos-1; i++)
316 for(int j=i+1; j<nElementos; j++)
317 if (obj.estado.Find(estado[i]) > obj.estado.Find(estado[j]))
318 dist++;
319 }
320 else if (tipo == distSpearmanFootruleCP) {
321 // soma das diferenças absolutas das posições
322 for (int i = 0; i < nElementos; i++)
323 dist += abs(i - obj.estado.Find(estado[i]));
324 }
325 else // Hamming
326 for (int i = 0; i < nElementos; i++)
327 dist += (estado[i] != obj.estado[i]);
328 return dist;
329}
ETiposDistanciaPermutacao
@ distKendallTauCP
@ distSpearmanFootruleCP
@ TIPO_DISTANCIA_CP
@ LIMITE_VIZINHOS_CP
@ TIPO_MUTAR_CP
@ TIPO_VIZINHO_CP
@ TIPO_CRUZAR_CP
ETiposVizinhancaPermutacao
@ vizInverterSegmentoCP
@ EXTRA_DEBUG
Nível extra para debug muito detalhado (uso interno).
Definition TProcura.h:68
TVector< int > _TV(const char *str)
Definition TVector.h:1154
void Debug(bool completo=true) override
Mostra o estado no ecrã, para debug.
void Cruzamento(TPonto a, TPonto b)
void Vizinhanca(TVector< TPonto > &vizinhos)
TPonto Duplicar(void)=0
Cria um objecto que é uma cópia deste.
void ResetParametros()
Inicializa os parametros, indicadores e instâncias.
void Copiar(TPonto objecto)
Fica com uma cópia do objecto.
int custo
Custo total, atualizada após Avaliar()
virtual void Vizinhanca(TVector< TPonto > &vizinhos)
void ResetParametros() override
Inicializa os parametros, indicadores e instâncias.
static bool memoriaEsgotada
Flag indicando problemas de memória esgotada.
Definition TProcura.h:501
int Parametro(int id) const
Definition TProcura.h:522
static int resultado
Resultado retornado pelo algoritmo na última execução.
Definition TProcura.h:493
static TVector< TParametro > parametro
Parâmetros a serem utilizados na configuração atual.
Definition TProcura.h:485
TVector< Item > & RandomOrder()
Coloca os elementos em ordem aleatória (Fisher–Yates shuffle).
Definition TVector.h:752
TVector< Item > & Reset(Item const &i)
Preenche todo o vetor com um mesmo valor.
Definition TVector.h:784
int Count() const
Definition TVector.h:227
unsigned int rand(int seq)
Retorna o próximo valor pseudo-aleatório.
Definition TRand.cpp:46