Skip to content

Commit 580d391

Browse files
committed
Foco no HillClimbing, codigo completo no fim
1 parent 1111838 commit 580d391

File tree

1 file changed

+126
-80
lines changed

1 file changed

+126
-80
lines changed

material/aulas/aula05/index.md

Lines changed: 126 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,132 @@ Hill Climbing, ou Subida da Encosta, é um algoritmo de busca local utilizado pa
312312
A principal vantagem dessa abordagem é que ela evita a explosão combinatória típica da busca exaustiva. Enquanto a busca completa avalia todas as possíveis combinações, que cresce exponencialmente com o número de entregas, Hill Climbing explora apenas uma pequena parte do espaço de busca, focando em melhorar progressivamente uma solução. Isso torna o método mais escalável para valores maiores de N, onde a busca exaustiva se torna inviável.
313313

314314

315+
```cpp
316+
// Hill Climbing
317+
vector<int> hillClimbing(const Ponto& motorista,
318+
const Ponto& coleta,
319+
const vector<Ponto>& entregas) {
320+
321+
int n = entregas.size();
322+
323+
// Solução inicial sequencial
324+
vector<int> atual(n);
325+
for (int i = 0; i < n; i++)
326+
atual[i] = i;
327+
328+
double melhorCusto = calcularCusto(motorista, coleta, entregas, atual);
329+
330+
bool melhorou = true;
331+
332+
while (melhorou) {
333+
334+
melhorou = false;
335+
vector<int> melhorVizinho = atual;
336+
337+
for (int i = 0; i < n - 1; i++) {
338+
for (int j = i + 1; j < n; j++) {
339+
340+
vector<int> vizinho = atual;
341+
swap(vizinho[i], vizinho[j]);
342+
343+
double custoVizinho = calcularCusto(motorista, coleta, entregas, vizinho);
344+
345+
if (custoVizinho < melhorCusto) {
346+
melhorCusto = custoVizinho;
347+
melhorVizinho = vizinho;
348+
melhorou = true;
349+
}
350+
}
351+
}
352+
353+
atual = melhorVizinho;
354+
}
355+
356+
return atual;
357+
}
358+
```
359+
360+
## Aleatoriedade
361+
Se utilizarmos aleatoriedade para escolher as rotas iniciais antes de aplicar a heurística poderiamos encontrar as soluções melhores mais rapidamente?
362+
363+
364+
Quando usamos Hill Climbing “puro”, ele é determinístico: dada a mesma solução inicial e a mesma regra de vizinhança, ele sempre percorre o mesmo caminho e para no mesmo ponto. Isso é polêmico, o algorítimo pode sempre cair nos mesmos minimos locais
365+
366+
A aleatoriedade entra justamente para quebrar esse comportamento rígido.
367+
368+
Em vez de sempre começar da mesma solução ou explorar vizinhos em uma ordem fixa, colocamos elementos aleatórios para diversificar a exploração do espaço de busca. Isso ajuda o algoritmo a escapar de mínimos locais, explorar regiões diferentes do espaço e, estatisticamente, encontrar soluções melhores.
369+
370+
371+
A aleatoriedade pode ajudar nesses pontos:
372+
373+
Primeiro, na solução inicial. Em vez de começar sempre com a ordem 0,1,2,...,N-1, você pode gerar uma permutação aleatória. Isso faz com que cada execução comece em um ponto diferente. Esse é o conceito de Multi-Start: executar Hill Climbing várias vezes com soluções iniciais diferentes e guardar a melhor solução encontrada.
374+
375+
Segundo, na escolha da vizinhança. Em vez de testar todos os vizinhos possíveis e escolher o melhor, você pode sortear dois índices aleatórios e testar apenas essa troca. Se melhorar, aceita. Caso contrário, tenta outra. Isso reduz o custo por iteração e torna a trajetória imprevisível.
376+
377+
## Desafio!!!
378+
379+
**1 — Tornar a solução inicial aleatória**
380+
Em vez de preencher o vetor sequencialmente, pense em como embaralhar esse vetor usando uma função de randomização pronta do C++.
381+
382+
383+
**2 — Alterar a geração de vizinhos**
384+
Em vez de dois loops aninhados testando todas as trocas possíveis (i,j), tente:
385+
386+
sortear dois índices distintos
387+
388+
trocar temporariamente
389+
390+
calcular o custo
391+
392+
decidir se aceita
393+
394+
Pergunta importante: como evitar recalcular o custo completo da rota a cada pequena troca? Existe alguma forma incremental?
395+
396+
**4 — Implementar múltiplos recomeços**
397+
Crie um laço externo que execute Hill Climbing várias vezes.
398+
A cada execução:
399+
400+
gere uma solução inicial aleatória
401+
402+
execute o Hill Climbing
403+
404+
compare com a melhor solução global
405+
406+
Pergunta: como você deve armazenar a melhor solução global sem fazer cópias desnecessárias a cada iteração?
407+
408+
**5 — Definir critério de parada**
409+
Cuidado para não ficar preso eternamente nos loops, um critério de parada é fundamental. Qual critério faz mais sentido neste contexto?
410+
411+
A ideia central é que aleatoriedade não é “bagunça”. Ela é um mecanismo controlado para aumentar diversidade na exploração do espaço de soluções. Em problemas combinatórios grandes, isso quase sempre melhora a qualidade média das soluções encontradas, mesmo que não garanta a ótima global.
412+
413+
414+
415+
## Para analizar as implementações:
416+
417+
Faça os testes para **N = 10, 11, 12 e 13**
418+
419+
1- Comparando Busca Exaustiva otimizada, Branch and Bound, Hill Climbing puro e O Hill Climbing aleatório, qual apresentou melhor escalabilidade conforme N aumentou?
420+
421+
422+
2 - O Hill Climbing puro encontrou a mesma solução que a busca exaustiva? O que será que aconteceu?
423+
424+
425+
3 - Usando O Hill Climbing aleatório, melhorou a qualidade média das soluções? Houve aumento significativo no tempo total? Analise o custo-benefício.
426+
427+
428+
4 Se você tivesse que resolver o problema para N = 100, qual abordagem escolheria e por quê? Considere tempo, qualidade da solução e escalabilidade.
429+
430+
431+
432+
[Submeta a sua entrega pelo Classroom diponível neste link até 06/03 ás 14h00](https://classroom.github.com/a/XI5jzrP-)
433+
434+
A entrega deve conter o seu algorítmo e as suas análises (pode deixar as análises no README.md)
435+
436+
437+
438+
# Código completo com o Hill Climbing
439+
440+
315441
```cpp
316442
#include <iostream>
317443
#include <vector>
@@ -478,83 +604,3 @@ int main(int argc, char* argv[]) {
478604
}
479605
480606
```
481-
482-
## Aleatoriedade
483-
Se utilizarmos aleatoriedade para escolher as rotas iniciais antes de aplicar a heurística poderiamos encontrar as soluções melhores mais rapidamente?
484-
485-
486-
Quando usamos Hill Climbing “puro”, ele é determinístico: dada a mesma solução inicial e a mesma regra de vizinhança, ele sempre percorre o mesmo caminho e para no mesmo ponto. Isso é polêmico, o algorítimo pode sempre cair nos mesmos minimos locais
487-
488-
A aleatoriedade entra justamente para quebrar esse comportamento rígido.
489-
490-
Em vez de sempre começar da mesma solução ou explorar vizinhos em uma ordem fixa, colocamos elementos aleatórios para diversificar a exploração do espaço de busca. Isso ajuda o algoritmo a escapar de mínimos locais, explorar regiões diferentes do espaço e, estatisticamente, encontrar soluções melhores.
491-
492-
493-
A aleatoriedade pode ajudar nesses pontos:
494-
495-
Primeiro, na solução inicial. Em vez de começar sempre com a ordem 0,1,2,...,N-1, você pode gerar uma permutação aleatória. Isso faz com que cada execução comece em um ponto diferente. Esse é o conceito de Multi-Start: executar Hill Climbing várias vezes com soluções iniciais diferentes e guardar a melhor solução encontrada.
496-
497-
Segundo, na escolha da vizinhança. Em vez de testar todos os vizinhos possíveis e escolher o melhor, você pode sortear dois índices aleatórios e testar apenas essa troca. Se melhorar, aceita. Caso contrário, tenta outra. Isso reduz o custo por iteração e torna a trajetória imprevisível.
498-
499-
## Desafio!!!
500-
501-
**1 — Tornar a solução inicial aleatória**
502-
Em vez de preencher o vetor sequencialmente, pense em como embaralhar esse vetor usando uma função de randomização pronta do C++.
503-
504-
505-
**2 — Alterar a geração de vizinhos**
506-
Em vez de dois loops aninhados testando todas as trocas possíveis (i,j), tente:
507-
508-
sortear dois índices distintos
509-
510-
trocar temporariamente
511-
512-
calcular o custo
513-
514-
decidir se aceita
515-
516-
Pergunta importante: como evitar recalcular o custo completo da rota a cada pequena troca? Existe alguma forma incremental?
517-
518-
**4 — Implementar múltiplos recomeços**
519-
Crie um laço externo que execute Hill Climbing várias vezes.
520-
A cada execução:
521-
522-
gere uma solução inicial aleatória
523-
524-
execute o Hill Climbing
525-
526-
compare com a melhor solução global
527-
528-
Pergunta: como você deve armazenar a melhor solução global sem fazer cópias desnecessárias a cada iteração?
529-
530-
**5 — Definir critério de parada**
531-
Cuidado para não ficar preso eternamente nos loops, um critério de parada é fundamental. Qual critério faz mais sentido neste contexto?
532-
533-
A ideia central é que aleatoriedade não é “bagunça”. Ela é um mecanismo controlado para aumentar diversidade na exploração do espaço de soluções. Em problemas combinatórios grandes, isso quase sempre melhora a qualidade média das soluções encontradas, mesmo que não garanta a ótima global.
534-
535-
536-
537-
## Para analizar as implementações:
538-
539-
Faça os testes para **N = 10, 11, 12 e 13**
540-
541-
1- Comparando Busca Exaustiva otimizada, Branch and Bound, Hill Climbing puro e O Hill Climbing aleatório, qual apresentou melhor escalabilidade conforme N aumentou?
542-
543-
544-
2 - O Hill Climbing puro encontrou a mesma solução que a busca exaustiva? O que será que aconteceu?
545-
546-
547-
3 - Usando O Hill Climbing aleatório, melhorou a qualidade média das soluções? Houve aumento significativo no tempo total? Analise o custo-benefício.
548-
549-
550-
4 Se você tivesse que resolver o problema para N = 100, qual abordagem escolheria e por quê? Considere tempo, qualidade da solução e escalabilidade.
551-
552-
553-
554-
[Submeta a sua entrega pelo Classroom diponível neste link até 06/03 ás 14h00](https://classroom.github.com/a/XI5jzrP-)
555-
556-
A entrega deve conter o seu algorítmo e as suas análises (pode deixar as análises no README.md)
557-
558-
559-
560-

0 commit comments

Comments
 (0)